游戲同步機制
在多人對戰(zhàn)的游戲中,游戲的每一方客戶端需要保持每一個時刻大家的數(shù)據(jù)是一致的,常見的同步方式分為幀同步和狀態(tài)同步,幀同步服務(wù)器不需要知道游戲邏輯,只是將客戶端的操作進行轉(zhuǎn)發(fā),然后客戶端自己計算邏輯,狀態(tài)同步是服務(wù)器計算游戲邏輯,并將角色狀態(tài)返回給客戶端,客戶端直接使用服務(wù)器返回的狀態(tài)即可。常見的RTS,Moba一般是幀同步,mmorpg一般是狀態(tài)同步。
幀同步的概念
總所周知,游戲是一幀一幀渲染在屏幕上的,我們一般稱之為渲染幀,渲染幀是不穩(wěn)定的,如果一幀計算的東西太多或者畫面太復(fù)雜,這一幀的時間可能會比較長,同一款游戲在不同的CPU,顯卡上,渲染幀也是不盡相同的。而幀同步的幀是指邏輯幀,非渲染幀。我們以2臺手機為例,他們需要同步,意味著他們的數(shù)據(jù)是一致的,如何保證他們數(shù)據(jù)一致呢,保證它們的起始狀態(tài)是一致的,執(zhí)行操作的時間是一致的,執(zhí)行的操作是一致的,那么2臺機器的結(jié)果一定是一致的。假如我們將游戲固定為1秒20個邏輯幀,即每50ms執(zhí)行一次邏輯幀,2臺手機都將在第5幀的時候執(zhí)行A的移動操作,都將在第12幀的時候執(zhí)行B的攻擊操作,這樣2臺手機無時無刻不保持著一致,這就是幀同步的概念。
幀同步的準(zhǔn)備工作
在做幀同步之前,需要頭腦清晰的知道所有的游戲邏輯都需要拆成每個邏輯幀去執(zhí)行,例如計算傷害,生命恢復(fù)等,這些都是在每一個邏輯幀去做的事情。游戲按照你的邏輯幀,不停的計算著數(shù)據(jù),這樣游戲就按邏輯幀走起來了,至于渲染到屏幕上,渲染30幀還是60幀,跟你的數(shù)據(jù)運算沒有關(guān)系。
帶關(guān)鍵幀的幀同步實現(xiàn)流程
- 設(shè)定游戲的邏輯幀率和關(guān)鍵幀率,在這我們假定游戲1s執(zhí)行20個邏輯幀,每5幀是一個關(guān)鍵幀。
- 服務(wù)器1s向客戶端廣播所有的關(guān)鍵幀,在這,服務(wù)器每1s向客戶端廣播4次關(guān)鍵幀,每次廣播內(nèi)容為上一個關(guān)鍵幀到這一個關(guān)鍵幀之間玩家的所有操作,例如A在第7幀要執(zhí)行移動命令。
- 客戶端收到服務(wù)器廣播的關(guān)鍵幀后,開始執(zhí)行所有的幀操作,例如A在第7幀要執(zhí)行移動命令。如果這段時間沒有任何操作,意味著這段時間玩家沒有操作。游戲每一幀都要執(zhí)行正常的游戲邏輯,該回血的回血,該攻擊的攻擊,跟關(guān)鍵幀是否攜帶操作信息沒有關(guān)系,只要收到關(guān)鍵幀,則一直執(zhí)行到當(dāng)前收到的最大關(guān)鍵幀為止。
- 客戶端的每次操作不會立即生效,而是上傳給服務(wù)器,客戶端執(zhí)行操作的時間都收到服務(wù)器發(fā)送的為準(zhǔn),服務(wù)器保證的是所有客戶端都以同一幀執(zhí)行該操作。
流程圖如下:

細節(jié)相關(guān)
- unity的Update是渲染幀的每一幀,請勿將邏輯直接寫在Update里,一次Upadte可能會跑好幾次邏輯幀,也可能一次都不跑,但是可以用Update去調(diào)用邏輯幀的Update,需要自行判斷當(dāng)前時候可執(zhí)行邏輯幀,以及應(yīng)該執(zhí)行幾次。
- 客戶端上傳操作的時候,加上預(yù)計該操作執(zhí)行的幀,因為客戶端的幀比服務(wù)器的慢,加上網(wǎng)絡(luò)延遲的原因,客戶端實際執(zhí)行該操作以服務(wù)器校驗后的為準(zhǔn),比如A在第5幀做了移動操作,我們傳給服務(wù)器的是預(yù)計第10幀進行移動操作,如果服務(wù)器收到該條命令的時候,還沒有向客戶端廣播過第10幀的內(nèi)容,無需額外設(shè)置,如果服務(wù)器收到該條命令的時候已經(jīng)廣播過第10幀的內(nèi)容,則需要將操作的幀自動往后順延到下一次的關(guān)鍵幀內(nèi)。
- 拋棄掉浮點數(shù),因為浮點數(shù)的運算跟CPU相關(guān),不同設(shè)備計算出的浮點數(shù)會有誤差,任何誤差對幀同步都是大忌,可以自己實現(xiàn)一套浮點數(shù),最簡單的就是存成long類型,通過倍數(shù)轉(zhuǎn)換實現(xiàn),1000代表浮點數(shù)的1,0.001用1表示,自己按這套規(guī)則去運算就可以了。
- 隨機數(shù)也可以自己實現(xiàn)一套,利用相同的種子,隨機數(shù)就是一樣的,這個也是在幀同步中必須保證的。