帧同步学习记录
幀同步
參考鏈接
- 細談網絡同步在游戲歷史中的發展變化(上)
- 細談網絡同步在游戲歷史中的發展變化(下)
網易雷火
- cocos2dx lua socket 使用
- cocos creator 項目總結二(戰斗幀同步解析)
- 2 天做了個多人實時對戰,200ms 延遲竟然也能絲滑流暢?
不是標題黨,講的非常完善清晰,而且還有狀態同步的例子
- Unity游戲開發 幀同步戰斗框架 理論篇
- Unity游戲開發 幀同步戰斗框架 框架篇
兩篇學會幀同步
-
Unity幀同步解決方案(一)
-
Unity幀同步解決方案(二)
-
Unity 游戲開發總結
大佬的專欄,還有很多Unity的知識 -
《王者榮耀》技術總監復盤回爐歷程:沒跨過這三座大山,就是另一款MOBA霸占市場了
一. 簡介
幀同步和狀態同步是目前最常用的游戲同步設計。它們并不互斥,可以一起相輔相成的出現于同步邏輯中。
下圖來自 Unity游戲開發 幀同步戰斗框架 理論篇
二. 客戶端邏輯
幀同步的邏輯都在客戶端,所以首要保證的是不同客戶端同一幀內的計算結果一定要相同。
- 可控的客戶端的邏輯
- 邏輯顯示分離
- 可控的隨機
1).客戶端幀同步邏輯
unity游戲開發 幀同步戰斗框架 框架篇
幀同步的邏輯全都在客戶端計算,必須保證每個客戶端相同幀的計算結果是一樣的。
要完全控制客戶端的計算流程,比如,移動,碰撞,動畫事件,延遲處理(等待s秒)等。
渲染因為跟不同硬件設備以及引擎有著相對較強的關聯,所以客戶端會設計成邏輯與顯示分離。
渲染部分可以交給引擎提供的更新,而邏輯更新必須由客戶端實現的Update控制。
1.主要邏輯
Update(delta){事件幀邏輯幀 }UpdateRender(delta){渲染幀 }- 事件幀:幀同步的幀,包含某段時間內所有玩家的操作
- 邏輯幀:游戲的所有邏輯
- 渲染幀:顯示部分的更新,比如坐標
1個事件幀 = n個邏輯幀 = n*m 個渲染幀
2.統一時間間隔
事件幀和邏輯幀是一起更新的,邏輯幀間隔小于等于事件幀。使用更小的間隔來判斷 deltaTime。
要注意的是,Update 傳入的間隔時間不是固定的,是變化的。比如 前臺 -> 后臺,后臺 -> 前臺。這時候傳入的時間就會很大。
#define 時間幀更新間隔 #define 邏輯幀更新間隔Update(delta){delta 計算if(delta < 邏輯幀時間間隔)return;間隔x次邏輯幀 = math.min(delta/邏輯幀更新間隔, 剩余事件幀數量)for(ini i = 0;i < 間隔x次邏輯幀;i ++){//事件幀Event(邏輯幀更新間隔)//邏輯幀Logic(邏輯幀更新間隔)} }Event(deltaTime){更新次數 + 1if(更新次數 < n) returnif(是否有事件幀) {邏輯幀更新次數 = 0return;}//分發更新次數 = 0邏輯幀更新次數 = n }Logic(deltaTime){if(邏輯幀更新次數 <= 0) return;邏輯幀更新次數 - 1//進行邏輯幀更新,,, }傳入的間隔時間經過處理,每次更新間隔就是邏輯幀間隔時間。這樣確保了即使是不同客戶端,不同間隔時間,每幀的更新也一定是同樣的間隔時間。
3.斷線重連和回放
回放:幀同步天然支持回放,把整局游戲按幀回放即可。
斷線重連:想想回放的邏輯,追幀加速即可。
2).邏輯顯示分離
1.保證不同客戶端結果相同
比如,動畫系統。
游戲中的行為,交互都是跟動作有關的。
比如攻擊動畫在 x 秒的動作打開碰撞,x秒的動作關閉碰撞。在x秒的時候生成一道劍氣等等。如果你的動畫系統不在你的控制之中,那么有可能在不同的設備上,不正確的時間點進行對應的行為。
目前的做法是用一組技能點隊列來控制動畫,而不是動畫的某一幀來觸發事件。每次更新的時候進行技能點的檢測,以及生成對應行為。
2.平滑卡頓
幀同步只會同步操作,而且一般來說手機端都是用 20-30 網絡幀同步來制作的。
30幀基本就是人眼卡頓的極限了。顯示和邏輯分離則仍可以使用30幀以上的渲染更新,以及使用插值的來平滑卡頓。
3.作弊檢測
每隔x幀,各個客戶端向服務器端發送檢驗數據,如果都一樣則通過,數據異常則可能是bug或作弊。
3).可控的隨機
幀同步的邏輯都是客戶端在計算的,所以得保證每個客戶端計算的結果要一致。那么對于一些不確定的邏輯就要給予確定性。
1.隨機數
可以參考如下鏈接的做法:
- Unity游戲開發 幀同步戰斗框架 理論篇
- 隨機數生成算法
目前項目是很簡單粗暴的做法。隨機生成了一個 x 長度的隨機隊列,每次隨機數按順序從里面取,取到隊尾再回頭取。
如果隨機數隊列有變化,那之前的回放就不可查看了。
2.浮點數
浮點數帶來的誤差,比如計算概率屬性(暴擊傷害,百分比治療等等),碰撞(小數帶來的碰撞誤差),以及循環增減時的低位浮點數累計問題等。
基本做法:
混合使用即可。目前只用了第二種,計算結果(屬性變化,位置移動等)向下取整( math.floor() )。
3.map和array
同樣,常用的字典類型也基本不能使用,應該都用隊列這種固定順序的數據結構來存儲。
但是字典類型方便查找,都用隊列肯定會降低查找效率以及代碼的工整性。
解決的方法就是實現一個數據結構,內部同時使用 字典和隊列 來維護當前數據,實現這組數據的增刪改查等邏輯即可。
4).預測/回滾
預測、回滾、快照是一起出現的,因為幀同步的邏輯延遲和網絡固定的延遲,以及數據的拆解和gc等等各種因素。
實際同步肯定會有些許的卡頓。常用的方法就是客戶段對當前的邏輯進行預測(1幀),先進行當前幀的模擬。并且存儲當前游戲的快照。
如果服務器發送下來的操作導致預測結果出錯,則快速回滾到前一幀,并執行正確的邏輯,回到當前幀再進行下一幀的預測。
暫時還沒做到這塊,對快照存儲還有些疑問。具體概念參考如下文章:
2 天做了個多人實時對戰,200ms 延遲竟然也能絲滑流暢?
三.網絡處理
1).TCP/UDP
TCP是一般使用的法案。但想要快肯定用UDP,目前安全的UDP庫也很多,可以直接使用。
四.調試工具
總結
- 上一篇: python浏览器自动化测试仪器_【松勤
- 下一篇: 国家测绘地理信息局黑龙江基础地理信息中心