幀同步方案下UnityEngine.Time的坑

聲明:本文所用Unity版本為2021.3.2f1c1。Mac使用的是MacBook Pro (16-inch, 2019)涩哟,CPU型號為2.3GHz 八核Intel Core i9索赏。Windows所用CPU型號為11th Gen Intel(R) Core(TM) i7-11700K @ 3.60GHz

幀同步與時間

幀同步贴彼,游戲開發(fā)常見的同步方案潜腻。簡單來說就是讓各個客戶端的邏輯部分,按照固定的速度進行心跳器仗。在這里融涣,時間就是控制每個客戶端邏輯幀率的唯一變量。

在Unity開發(fā)中精钮,因為幀同步需要定幀威鹿,所以最常見的定幀的方式有兩種:使用Unity的FixUpdate,或著自己管理時間轨香。

FixUpdate只需要把它的DeltaTime設(shè)置成所需要的時間即可忽你,我們著重說第二種:自己管理時間。

double time;                   // 時間累積
double interval;               // 邏輯幀間隔

void Update(float delta)
{
    time += delta;
    while (time >= interval)
    {
        time -= interval;
        LogicTick();            // 邏輯幀心跳
    }
}

正如上面代碼展示臂容,我們通過累積時間科雳,每滿足一次邏輯幀的幀率時間,就進行一次邏輯心跳脓杉,并將累積時間減去一個邏輯幀間隔時間糟秘。這里函數(shù)的參數(shù),就可以傳入UnityEngine.Time.deltaTime球散。

問題的出現(xiàn)

現(xiàn)在問題來了尿赚,當(dāng)我實際去運行的時候,發(fā)現(xiàn)同樣的一套代碼所寫的邏輯,mac端就是比windows端延遲感更明顯吼畏。

為了查明問題,我專門實時顯示了兩端與服務(wù)器的RTT嘁灯,結(jié)果發(fā)現(xiàn)RTT均在30ms以內(nèi)泻蚊,說明問題不在這里。

之后我才去監(jiān)測二者每次邏輯心跳所對應(yīng)的邏輯幀號與服務(wù)器幀號丑婿,結(jié)果大出意料:mac端的時間比windows端過得要慢性雄,而且隨著時間的累積效應(yīng),mac端會越來越卡(類似于延遲時間越來越大)羹奉。

對這個問題進行排查秒旋,我將問題定位到了UnityEngine.Time.deltaTime。從我們對時間的理解诀拭,當(dāng)Time.timeScale為1時迁筛,Time.unscaledDeltaTimeTime.deltaTime與應(yīng)當(dāng)是一致的。但是當(dāng)我們在某一個心跳函數(shù)內(nèi)比較這兩個值時會發(fā)現(xiàn)耕挨,Time.unscaledDeltaTime并不總是等于Time.deltaTime细卧,時長會比這個大。而且每次出現(xiàn)不一致時筒占,Time.deltaTime的值總是一樣的贪庙。

所以最后,問題被鎖定到了Time設(shè)置里的Maximum Allowed Timestep選項翰苫。

PS:其實我曾經(jīng)一度以為是跨平臺導(dǎo)致Unity底層提供的deltaTime出現(xiàn)了偏差止邮。

Maximum Allowed Timestep的說明

關(guān)于Maximum Allowed Timestep這個配置的說明,Unity有一份官方的說明奏窑。結(jié)合我之前轉(zhuǎn)發(fā)的Unity的函數(shù)執(zhí)行順序导披,我們可以簡單理解為:

FixedUpdate在1次Update可能會執(zhí)行N次,N約等于Time.deltaTime / Time.fixedDeltaTime。假如Time.deltaTime變大缨硝,會導(dǎo)致下一幀FixedUpdate的執(zhí)行次數(shù)N變大新症,CPU的性能消耗變大,從而又會影響當(dāng)前Update的耗時滑沧。這種糟糕的情況可能需要相當(dāng)長的時間才能緩解過來。所以Maximum Allowed Timestep限制Time.deltaTime的最大值巍实,N的最大值也固定了滓技,防止出現(xiàn)“最壞”的情況。

解決方案

為了解決這個問題棚潦,我們所需要做的就是有一個方案能夠替換掉Time.deltaTime令漂。

為什么不使用Time.unscaledDeltaTime?因為在具體的項目中,我們依舊可能會用到Time.timeScale叠必,所以一切從項目實際出發(fā)(如果你的項目無所謂荚孵,那就大膽用吧)。

下面給出我的解決方案:

private long _lastFrameTicks;
private const double Ticks2Second = 0.0000001;
private double _delta;

public double Delta => _delta * UnityEngine.Time.timeScale;

public void Tick()
{
    long currFrameTicks = System.DateTime.Now.Ticks;
    _delta = (currFrameTicks - _lastFrameTicks) * Ticks2Second;
    _lastFrameTicks = currFrameTicks;
}

通過使用DateTime.Now.Ticks纬朝,計算兩次心跳之間的時間間隔收叶,再將時間間隔的單位轉(zhuǎn)換為秒,即可作為delta時間去使用共苛。

其實按照這個方案深入下去判没,依舊有很多點會決定我們Delta計算的正確性。比如這個Tick執(zhí)行的時機隅茎,Unity內(nèi)所有Update執(zhí)行的順序等澄峰。但是這些基本都不會影響我們幀同步內(nèi)時間的累積計算:多個客戶端同時開始幀同步運算,那么過去固定時間后辟犀,這些客戶端的幀號一定是相同的俏竞,而不會出現(xiàn)開頭我所描述的客戶端幀號不一致的bug。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末踪蹬,一起剝皮案震驚了整個濱河市胞此,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跃捣,老刑警劉巖漱牵,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異疚漆,居然都是意外死亡酣胀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門娶聘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闻镶,“玉大人,你說我怎么就攤上這事丸升∶” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵狡耻,是天一觀的道長墩剖。 經(jīng)常有香客問我,道長夷狰,這世上最難降的妖魔是什么岭皂? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮沼头,結(jié)果婚禮上爷绘,老公的妹妹穿的比我還像新娘书劝。我一直安慰自己,他們只是感情好土至,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布购对。 她就那樣靜靜地躺著,像睡著了一般陶因。 火紅的嫁衣襯著肌膚如雪洞斯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天坑赡,我揣著相機與錄音,去河邊找鬼么抗。 笑死毅否,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蝇刀。 我是一名探鬼主播螟加,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吞琐!你這毒婦竟也來了捆探?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤站粟,失蹤者是張志新(化名)和其女友劉穎黍图,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奴烙,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡助被,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了切诀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揩环。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖幅虑,靈堂內(nèi)的尸體忽然破棺而出丰滑,到底是詐尸還是另有隱情,我是刑警寧澤倒庵,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布褒墨,位于F島的核電站,受9級特大地震影響哄芜,放射性物質(zhì)發(fā)生泄漏貌亭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一认臊、第九天 我趴在偏房一處隱蔽的房頂上張望圃庭。 院中可真熱鬧,春花似錦、人聲如沸剧腻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽书在。三九已至灰伟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間儒旬,已是汗流浹背栏账。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留栈源,地道東北人挡爵。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像甚垦,于是被迫代替她去往敵國和親茶鹃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容