和MMORPG不同,實時動作型網絡游戲 追求操作的響應要求極高(<150ms)。
動作型網絡游戲的制作人希望做到單機游戲的體驗,網絡游戲的服務。
網絡指令在多客戶端間的同步算法,從原理上來說,圍繞兩種特性的取舍而定:
* 犧牲局部實時性:某程度的互等待,保證各客戶端間指令集在指定時間段一致。
* 犧牲局部一致性:容許客戶端本機先行模擬,等待后續指令到達糾正。(DR)
網絡的存在導致魚與熊掌不可兼得,所以現在市面上的動作網絡游戲都有
如下的妥協和折衷實現:
* 在客戶端本機上算大量關鍵運算來保證手感
* 玩法上對直接進行的決定性互動的要求不高
* 接受時不時網絡延遲導致等待的缺點來維持復雜精確的玩法
* 策划維持可玩性的底線下對一些一致性的要求減低
實時性需求非常高的網絡游戲,舍是一種關鍵藝術。
FPS,賽車,RTS,泡泡堂/QQ堂,模擬器聯網等類型的網絡游戲在一定程度上
都有以上的一個或多個取舍抉擇。
---------------------------------------------------------------------
在很多實時同步的網絡游戲中,都用到UDP而不是MMORPG中的TCP進行
非關鍵消息的同步(更有些賽車類型的游戲可能直接起用p2p網絡互聯):
非關鍵消息允許丟包,可對物體狀態做客戶端預測補償;UDP甚至可方便地穿牆;
所以UDP比TCP在這種情況下更合適。Dead Reckoning是常用的客戶端
預測的技術,而更細節的客戶端預測對不同類型的游戲而言有不同的擴展。
這方面的技術在之前的HalfLife / Quake3 / CounterStrike等UDP中心
服務器做動作認證的FPS游戲中應用得比較成熟。
雖然覺得真正的p2p網狀互聯的動作同步不適合網游(一致性和防外掛考慮),
但觀察了幾個游戲后發現泡泡堂,跑跑卡丁車,QQ飛車,名將三國等一些游戲
確實不同程度上使用網狀p2p(有些在公共場景組隊就啟用p2p進行位置同步),
而且有些的收發包分別都達到20個/秒的量,幾乎趕上渲染幀率的一半。
直觀的猜想是它們玩家間動作顯示上具實時性,但關鍵交互結果是不具實時性的。
而道具的使用大部分都提倡 范圍化 和 時延化,以減少網絡延遲的影響。
這樣可以簡單地提高udp發包頻率和數量,客戶端盡情模擬后拉扯:
如果大家不作弊,如果平均每秒接到的包夠多,簡單插值和預測一下自然很平滑。
而關鍵的屬性改變,戰場物品掉落,死亡,勝利等,則用非實時的中心服務器
信息保證保證結果唯一性。
雖然如此,還是覺得p2p的體系應該有一定的peer間同步法則。
之前沒了解過p2p體系的同步知識,所以先查閱了一些比較容易找到的paper,
所描述的分布式狀態同步算法大致有如下幾種。
---------------------------------------------------------------------
Lockstep Synchronization
最直觀同步方案:任何peer的action要得到其他所有peer的同意才能發起。
見下圖:
如果使用非網狀的p2p模型,提供peer master來做統一狀態運算,
那lockstep模型便成為嚴格的幀同步模型,這是大多RTS,模擬器聯網,
以及一些提供建主機后連接的休閑動作游戲采用的同步模型;通過頻繁
對時,便可以像編寫串行單機指令一樣來進行多個peer的事件指令同步。
lockstep原是監獄用語,指犯人列隊步行時的同步串鏈式行進,非常形象。
最初並非設計用於游戲,而是軍方的軍事互動仿真程序。IEEE DIS標准指出:
100-300ms的雙程總延時,對軍事性互動仿真模擬是可接受的。而根據一些統計,
第一人稱射擊游戲中的玩家雙程延遲普遍在50-300ms的區間內。
而如果玩家都在一個LAN內進行p2p連接通信,雙程延遲可能控制在20ms以內。
優點:簡單易實現,不會出現任何的不一致性。
在延遲小(round-trip < 100ms)且穩定的環境下非常合適。
在實時性要求不高的玩法(比如回合制玩法)中也非常合適。
缺點:游戲節奏受最慢的peer影響巨大。一人卡機,所有人受影響。
惡意的peer可以用偽造大延遲的方式來獲得好處,從而破壞游戲公平性。
---------------------------------------------------------------------
Bucket Synchronization
見下圖:
原paper很長,這里只按照個人理解編排步驟:
(原文是徹底分布式的網狀p2p,為方便理解,下面將player B稱為peer master,
並假設它負責對時任務,以省掉NTP對時系統的理解過程)
1. 設定最大容忍延遲值為 PlayoutDelay(如120ms)。
PlayoutDelay為:peer master執行指令N的時刻 - 遠程peer的指令N發出時刻所對應的bucket時間段起始時間
2. 設定游戲時間軸上每隔BucketFrequency(如40ms)歸一個新bucket來存放動作指令。
3. 開始游戲前,peer master發送對時命令給所有peer進行對時。
4. 因為peer master知道所有peer的平均延遲 AvgLag,那它執行步驟3后,
延遲 AvgLag 時間后,開始游戲邏輯。
5. peer master自身發出的操作指令,雖然不需要經過網絡,但也需要強行延遲
投遞到Ti對應的bucket中,其中:
Ti = 當前時刻所屬bucket時間段的起始時間 + PlayoutDelay
6. 如果peer master接到一個動作指令,但:
peer master當前時間 - 動作指令攜帶的發送時間 > PlayoutDelay
那peer master會直接丟棄這個動作指令(也就是將超時到達的指令當作無效)
7. 如果peer master接到的動作指令不超過上述6中描述的范圍,那會把這個指令
放入Ti所對應的bucket中,其中:
Ti = 指令包攜帶的發送時間戳所在的bucket時間段起始時間 + PlayoutDelay
8. 每個bucket對應的時間段末端,peer master執行這個bucket中所有的指令,
將結果狀態更新到畫面。
9. 因為有網絡的存在,可能某些bucket中沒有指令,原版MiMaze游戲實現是不處理。
但paper中提供了基於Dead Reckoning的預測狀態顯示方法。
10. 游戲過程中,peer master以某種時間間隔作頻率進行各peer對時,
保證將各peer機器時間的誤差控制在一個可接受范圍內。
優點:不依賴最慢peer來決定游戲流暢度。流暢度是維持在平均預定義水平的。
缺點:對超過MaxLag的指令做丟棄。除了原paper中的3D吃豆人迷宮式游戲這種
經過特殊剪裁的游戲,動作游戲對延遲玩家的操作做丟棄,似乎很難想象。
---------------------------------------------------------------------
TimeWrap Synchronization
它是一個基於某些狀態支持回滾(rollback)的同步算法。有點類似HL的做法。
簡言之,就是對每個操作指令的執行后保存一個狀態快照(snapshot),
各個peer按照自己的預測先行顯示,但在發生一致性沖突的情況下,
回滾到上一個狀態,並重新將指令序列在基於回滾后的快照的基礎上再
執行一次,以獲得正確的當前狀態。
---------------------------------------------------------------------
Trailing State Synchronization
對TimeWrap Synchronization的一種改進。TimeWrap方案中建立snapshot是
以指令數量(1或少量幾個指令)間隔為單位;而TSS方案則以某種延遲值(100ms)
間隔為單位對游戲做snapshot(比如100ms前做一個,200ms前做一個...)。
當發生一致性沖突時,尋找最遠需要開始計算的snapshot,並將該snapshot到
現在為止的時間內的指令重新執行,得到正確的最新狀態。
---------------------------------------------------------------------
參考文章:
<<Minimization of Latency in Cheat-Proof Real-Time Gaming by Trusting Time-Stamp Servers>>
<<End-to-end transmission control mechanisms for multiparty interactive applicatins on the Internet>>
<<Dead Reckoning: Latency Hiding for Networked Games>>
<<An Efficient Synchronization Mechanism for Mirrored Game Architectures>>
---------------------------------------------------------------------