標籤:

狀態同步扣血匹配的坑

在之前的文章中《幀同步和狀態同步》提到過狀態同步在打擊感表現方面弱於幀同步。打擊感在遊戲中講究的是拳拳到肉的快感,也就是說操作、技能釋放、打擊反饋、扣血都能精準的銜接。

歐,打~

在這篇文章里來聊聊做狀態同步在扣血匹配上遇到的坑。

一、近戰攻擊遇到的問題

對於近戰攻擊的扣血,可以在動作幀上掛扣血觸發事件來實現比較精準的扣血匹配。但是,當攻擊單位在攻擊過程中死亡時,會出現攻擊動作沒有完成卻扣了血的現象。

第一種方案

伺服器給客戶端發送近戰攻擊命令,同時伺服器直接扣血,客戶端等動作到砍中幀進行扣血(為了保持客戶端和伺服器扣血一致,即使攻擊單位死了也會在同樣的時間扣血)。

近戰攻擊伺服器直接扣血

這個方案帶來的問題:

  1. 如果這一刀會導致被攻擊單位死亡,那麼這個單位直接會在伺服器死亡,死亡消息被發送到客戶端,結果看到的現象是:攻擊單位一抬手,對方就死了
  2. 即使攻擊單位在砍中幀之前死掉,被攻擊單位也會在預定的時間執行扣血。可能看到的想像是:某單位沒有被砍中就被扣血

第二種方案

為了解決問題1,伺服器延遲扣血。伺服器給客戶端發送近戰攻擊命令,伺服器等到固定的時長(動作起手到砍中幀的時長)後進行扣血。客戶端等動作到砍中幀進行扣血(為了保持客戶端和伺服器扣血一致,即使攻擊單位死了也會在同樣的時間扣血)。

近戰攻擊伺服器延遲扣血

這個方案解決了問題1,但是導致了問題2的衍生現象。如果已死單位已出手的這刀會殺死某單位,會看到的現象是:某單位沒有被砍中就死了,比問題2現象更明顯。

第三種方案

為了解決問題2以及衍生現象,嘗試了扣血取消機制。新的方案是:伺服器給客戶端發送近戰攻擊命令,伺服器等到固定的時長(動作起手到砍中幀的時長)後進行扣血嘗試(攻擊單位死了就不扣血),客戶端等動作到砍中幀觸發扣血(攻擊單位死了就不扣血)。

近戰攻擊加入扣血判定

這個方案帶來的問題:伺服器客戶端血量不一致。因為加入了扣血取消機制後,扣血是否執行是不確定的。產生血量不一致的關鍵在於,伺服器和客戶端對於扣血的取消是不一致的。是什麼導致了不一致:

  1. 從發起到扣血嘗試的時間間隔不一致,如圖所示,T1和T2的長度是不一致的。這是因為:(1)如果客戶端採用動作幀事件觸發扣血,客戶端發起動作、動作到達砍中幀都存在時間誤差。(2)如果客戶端採用時間計算觸發扣血,客戶端和伺服器幀的間隔不一致,有計算誤差(可以嘗試用統一的幀間隔處理扣血問題,但是這樣會降低客戶端處理扣血的幀頻率,導致扣血匹配精度下降,再加上動作和時間計算之間本來就存在誤差,導致近戰扣血難以完美匹配動作)。

扣血嘗試時間間隔

  1. 攻擊單位死亡不一致。攻擊單位的死亡由伺服器推送,網路消息包的延遲是存在波動的,這就導致判定結果出現不一致。

單位死亡點不一致

血量不一致導致的一個比較明顯的現象是:單位明明看起來沒有血了,但是打不死

第四種方案

由於血量不一致的問題感受更差,選擇回到第二種方案,並加以改進。第四種方案在第二種方案的基礎上加入單位死亡時flush自己發起的近戰扣血的機制。這個機制消除的現象:攻擊單位已經死亡(消失)一段時間後,還打出了傷害;產生的現象:攻擊單位死亡時瞬間打出傷害。從感受上來說,會更容易接受一些。

二、遠程攻擊遇到的問題

遠程攻擊要解決的問題是,客戶端子彈的命中和伺服器推的扣血如何精準匹配。由於子彈的飛行速度很快,伺服器不控制客戶端子彈的飛行。伺服器和客戶端的子彈各自控制自己的子彈飛行和命中。理想情況下,客戶端和伺服器的子彈飛行時間相同,延遲穩定。扣血和客戶端命中完美匹配。

完美情況下

然而,現實世界是不完美的。

  1. 飛行時間差異 這個一個原因是目標位置誤差,目標單位在伺服器和客戶端的位置是有誤差的。另一個原因是伺服器和客戶端的幀處理間隔不一致,這就導致兩者判定命中的時間誤差是不同的。

飛行時間不一致

  1. 網路波動問題 子彈產生的消息延遲和扣血消息延遲不一致,導致客戶端扣血和命中無法匹配。

網路波動

以上兩個比較難解決的問題,會導致扣血匹配不一致。另外還有一些容易解決的問題要注意:

  1. 創建即走問題。子彈在創建的當幀不要計算移動
  2. 子彈原點問題。有的子彈形狀比較長,要注意原點是箭頭、箭中、箭尾
  3. 客戶端非同步創建耗時。客戶端創建子彈模型可能是非同步的,不是馬上創建出來的。如果創建完成才移動會存在移動誤差。

還有一些措施可以掩蓋扣血匹配精度問題:

  1. 伺服器推的扣血晚到的情況:通過客戶端子彈產生的命中效果來提高打擊感,減弱對真實扣血的關注,可以比較好的銜接扣血。
  2. 伺服器推的扣血早到的情況:扣血可以等待客戶端子彈命中再表現出來。

另外一種遠程攻擊的命中方案

在開發的過程中採用過的一個方案是:伺服器不處理子彈的移動和命中,客戶端子彈命中後向伺服器發起一個RPC調用,返回扣血結果。這樣扣血延遲是一個RTT時間。

優點是:沒有各類誤差

缺點是:1.RTT時間本身就有一定的延遲 2.錄像需要記錄更多的數據 3.錄像回放存在一定的誤差


推薦閱讀:

skynet初探
記錄一次伺服器宕機分析過程(2)-深入Lua GC
卡牌戰鬥系統設計概述
遊戲線上的伺服器風險
通服整體架構設計概述

TAG:遊戲伺服器 |