幀鎖定算法解決游戲同步
早期 RTS,XBOX360 LIVE游戲常用同步策略,如何才能像單機游戲一樣編寫網游??
算法概念
該算法普遍要求網速RTT要在100ms以內,一般人數不超過8人,在這樣的情況下,可以像單機游戲一樣編寫網絡游戲。所有客戶端任意時刻邏輯都是統一的,缺點是一個人卡機,所有人等待。
1.客戶端定時(比如每五幀)上傳控制信息。
2.服務器收到所有控制信息后廣播給所有客戶。
3.客戶端用服務器發來的更新消息中的控制信息進行游戲。
4.如果客戶端進行到下一個關鍵幀(5幀后)時沒有收到服務器的更新消息則等待。
5.如果客戶端進行到下一個關鍵幀時已經接收到了服務器的更新消息,則將上面的數據用于游戲,并采集當前鼠標鍵盤輸入發送給服務器,同時繼續進行下去。
6.服務端采集到所有數據后再次發送下一個關鍵幀更新消息。
這個等待關鍵幀更新數據的過程稱為“幀鎖定”
應用案例:大部分RTS游戲,街霸II(xbox360),Callus模擬器。
算法流程
客戶端邏輯:
1. 判斷當前幀F是否關鍵幀K1:如果不是跳轉(7)。
2. 如果是關鍵幀,則察看有沒有K1的UPDATE數據,如果沒有的話重復2等待。
3. 采集當前K1的輸入作為CTRL數據與K1編號一起發送給服務器
4. 從UPDATE K1中得到下一個關鍵幀的號碼K2以及到下一個關鍵幀之間的輸入數據I。
5. 從這個關鍵幀到下 一個關鍵幀K2之間的虛擬輸入都用I。
6. 令K1 = K2。
7. 執行該幀邏輯
8. 跳轉(1)
服務端邏輯:
1. 收集所有客戶端本關鍵幀K1的CTRL數據(Ctrl-K)等待知道收集完成所有的CTRL-K。
2. 根據所有CTRL-K,計算下一個關鍵幀K2的Update,計算再下一個關鍵幀的編號K3。
3. 將Update發送給所有客戶端
4. 令K1=K2
5. 跳轉(1)

服務器根據所有客戶端的最大RTT,平滑計算下一個關鍵幀的編號,讓延遲根據網絡情況自動調整。
算法演示
我根據該算法將街機模擬器修改出了一個可用于多人對戰的版本,早期有一個叫做kaillera的東西,可以幫助模擬器實現多人聯機,但是并沒有作幀鎖定,只是簡單將鍵盤消息進行收集廣播而已,后來Capcom在PSP和360上都出過街霸的聯網版本,但是聯網效果不理想。這個算法其實局域網有細就經常使用了,只是近年來公網速度提高,很容易找到RTT<50ms的服務器,因此根據上述算法,在平均RTT=100ms(操作靈敏度1/10秒),情況下,保證自動計算關鍵幀適應各種網絡條件后,就能夠像編寫單機游戲一樣開發網游,而不需狀態上作復雜的位置/狀態同步。

從上圖的演示中可以看到,兩個模擬器進程都在運行1941這個游戲,兩邊客戶端使用了該算法,將邏輯統一在一個整體中。

最后這張圖是運行KOF99的效果圖,兩邊完美同步。