幀同步和狀態同步


實時游戲發展迅猛,同步技術也逐漸成為解決方案的核心之一。 本文簡單討論了幀同步和狀態同步。


幀同步

什么是幀同步:幀同步常被RTS(即時戰略)游戲常采用。在游戲中同步的是玩家的操作指令,操作指令包含當前的幀索引。一般的流程是客戶端上傳操作到服務器, 服務器收到后並不計算游戲行為, 而是轉發到所有客戶端。這里最重要的概念就是 相同的輸入 + 相同的時機 = 相同的輸出。

實現幀同步的流程一般是:

  1. 同步隨機數種子。(一般游戲中都設計隨機數的使用, 通過同步隨機數種子,可以保持隨機數一致性)

  2. 客戶端上傳操作指令。(指令包括游戲操作和當前幀索引)

  3. 服務器廣播所有客戶端的操作。(如果沒有操作, 也要廣播空指令來驅動游戲幀前進)。

因為幀同步的特性, 我們可以很方便的做出戰斗回放:服務器記錄所有操作, 客戶端請求到操作文件再執行一次即可。

幀同步的特性導致客戶端的邏輯實現和表現實現必須完全分離。Unity中的一些方法接口(如 Invoke, Update、動畫系統等)是不可靠的,所有要自己實現一套物理引擎、數學庫,做到邏輯和表現分離。 這樣即使Unity的渲染是不同步的,但是邏輯跑出來是同步的。

我曾經參與過一個飛機類彈幕游戲的項目,它的同步方案就是幀同步, 可以完美的播放回放, 並實現服務器上加速驗算。


狀態同步

什么是狀態同步:同步的是游戲中的各種狀態。一般的流程是客戶端上傳操作到服務器,服務器收到后計算游戲行為的結果,然后以廣播的方式下發游戲中各種狀態,客戶端收到狀態后再根據狀態顯示內容。狀態同步最廣泛的應用應該是在回合制游戲中。

狀態同步其實是一種不嚴謹的同步。它的思想中,不同玩家屏幕上的表現的一致性並不是重要指標, 只要每次操作的結果相同即可。所以狀態同步對網絡延遲的要求並不高。像玩RPG游戲,200-300ms的延遲也可以接受。 但是在RTS游戲中,50ms的延遲也會很受傷。
舉個移動的例子,在狀態同步中, 客戶端甲上操作要求從A點移動到B點,但在客戶端乙上, 甲對象從A移動到C,然后從C點移動到了B。這是因為, 客戶端乙收到A的移動狀態時, 已經經過了一個延遲。這個過程中,需要客戶端乙本地做一些平滑的處理,最終達到移動到B點的結果。

所以國產RPG游戲中,動畫的特效一般做的比較絢麗(大), 攻擊的時候給人感覺是擊中了。放技能之前一般也有一個動畫前搖,同時將攻擊請求提交給服務器。等服務器結果返回時,動畫也播放完畢了,之后就是統一的傷害效果和結算。


狀態同步和幀同步的比較和選擇:

比較:

  狀態同步 幀同步
流量 相對高 相對低
回放 記錄文件大 記錄文件小
安全性 服務器實現邏輯,安全性高 邏輯在客戶端,反外掛壓力大、無法避免開圖掛
服務器壓力
戰斗校驗 協議加密,內存混餚,誤差校驗,無法徹底解決。 服務器可以重啟跑一遍戰斗。
網絡卡頓的表現 瞬移,回位,莫名掉血 戰斗卡頓
實現 調優狀態同步方式,客戶端需要做插值處理。 客戶端按照單機方式開發,保證邏輯層和表現層分離。邏輯層不要用到浮點數,不要用不確定順序的邏輯結構。對於物理引擎和浮點數計算要不能使用Unity的。

選擇:對於單位比較多的即時策略游戲,幀同步是很好的選擇。反過來,如果玩家比較多,狀態同步更合適,安全性更高。


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM