所讀版本:機械工業出版社

這一篇在做什麼

前面幾篇大多在講網絡通信本身,這一篇把焦點轉到多人遊戲裡更實際的一個問題:玩家狀態到底要怎麼同步,才能在「延遲不可避免」的情況下,盡量讓所有人看到合理的結果。

同步的兩條主路

多人同步通常可以粗分成兩種思路:

  • 狀態同步
  • 指令同步

兩者不是單純誰高級誰落後,而是各自拿不同問題做交換。

狀態同步

狀態同步的核心是:直接同步角色的結果狀態,例如位置、朝向、血量等。

在最簡單的情況下,客戶端會定時把自己的位置發給服務端,再由服務端轉發給其他玩家。其他客戶端收到後,就把對方角色移動到指定位置。

問題:直接設位置會瞬移

這種做法雖然簡單,但很容易讓遠端角色看起來像瞬移,因此才會衍生出一些平滑策略。

跟隨算法

跟隨算法的想法是:收到對方新位置後,不立刻瞬移,而是讓遠端角色以某種速度跟過去。

它看起來比瞬移平順,但問題是誤差可能越積越大。

例如:

  • 玩家 1 實際路徑是 A -> B -> C
  • 玩家 1 經過 B 時送出同步消息
  • 玩家 2 還看到玩家 1 在 A
  • 玩家 2 收到消息後,才開始讓遠端角色往 B 移動

當玩家 2 畫面上的遠端角色終於到達 B 時,真實玩家可能已經跑到 C 了。

預測算法

另一種思路是預測。也就是說,收到對方當前狀態時,不是只把它補到當前點,而是估算它在下一個時刻應該到哪裡,提早把遠端角色往那個預測點帶。

這樣做的目的,是用一點估算來抵消網絡傳輸延遲帶來的落後感。

代價則是:一旦預測錯了,畫面就需要再修正回真實位置。

指令同步

和狀態同步不同,指令同步傳的不是「結果」,而是「操作」。

例如:

  • 玩家 1 按下 W
  • 客戶端把「前進」這個操作送給服務端
  • 服務端再把這個操作轉發給所有客戶端
  • 每個客戶端在本地執行同一條指令

這樣理論上只要邏輯一致,大家最後算出來的結果也會一致。

指令同步的問題

問題在於:不同機器的執行速度不一樣,幀率也不一樣。

結果就是:

  • 有些人本地跑得快
  • 有些人本地跑得慢
  • 即使收到的是同一條「前進」指令,最後也可能出現不同畫面結果

所以單純同步操作還不夠,還得進一步處理「時間」這個因素。

幀同步

幀同步可以看成指令同步的一種常見落地形式。它的核心不是只發送操作本身,而是把操作和某個同步幀綁在一起。

也就是說,客戶端不再問「我現在收到了什麼指令」,而是問:

  • 這條指令屬於第幾幀
  • 當我執行到那一幀時,應該做什麼

為什麼要固定同步幀

只要所有客戶端:

  • 使用同一套計算公式
  • 在相同的同步幀執行相同指令

那理論上結果就會一致。

一個簡化例子如下:

int frame = 0; //目前執行到第幾幀
float interval = 0.1f; //兩幀之間的理想時間
public void Update()
{
    while(Time.deltaTime < frame * interval)
    {
        FrameUpdate();
        frame++;
    }
}

它的目標是盡量保證:

  • N 秒左右時
  • 所有客戶端都執行到第 10 * N 幀附近

如果某幾幀執行時間拉長,系統就需要補跑後面的幀,盡量把進度追上。

幀同步真正保證的是什麼

幀同步真正想保證的不是「畫面每一刻都毫無差異」,而是:

  • 當所有客戶端都執行到同一個同步幀時
  • 它們的遊戲狀態應該一致

例如移動公式完全一樣,那麼只要執行了相同幀數,最終位移結果理論上也應該一致。

指令執行時的兩種妥協

即使有了同步幀,現實裡還是會碰到快慢客戶端不同步的問題。這時通常只剩下兩條取捨路線。

延遲執行

讓跑得快的客戶端等待跑得慢的客戶端。

好處是整體一致性更高,壞處是快客戶端的體驗會變差,因為它明明算得動,卻要等別人。

樂觀幀同步

另一條路是更偏「快的人優先」。如果某個慢客戶端送來的指令已經過時,就直接丟棄。

好處是整體節奏更流暢,壞處是慢客戶端可能明顯吃虧,因為它的輸入會更常失效。

網絡延遲沒有真正的終極解

這篇最後點出一個很現實的結論:網絡延遲本身基本無解。

能做的通常只有兩類補救:

減少要傳的數據

傳得越多,丟包與重傳機率通常越高,因此合理壓縮消息量本身就是同步體驗的一部分。

在客戶端做視覺修飾

很多時候,同步系統不是在「消滅延遲」,而是在「掩蓋延遲」。

例如:

  • 補間
  • 預測
  • 延遲顯示
  • 平滑修正

這些做法的本質,都是讓玩家更不容易感知到同步誤差。

這一篇先記住的重點

如果只保留最核心的判斷,可以收斂成:

  • 狀態同步傳結果,簡單但容易看到瞬移與修正
  • 指令同步傳操作,理論一致性高,但對時間控制要求更嚴
  • 幀同步是指令同步常見的落地方式
  • 多人同步本質上一直都在做「一致性、即時性、體驗感」之間的取捨
  • 網絡延遲無法消除,只能盡量減少影響、再用客戶端表現去掩蓋它