為什麼FPS對射的時候要來回跑--valve的多人對戰同步技術
01-29
//--前言
文章是老文章了,技術還在沿用,而且最近對射擊遊戲突然上癮,無奈射擊能力比較差(看來我還是比較適合rts),所以也把技術文章過一些出來,這個還是有些用的么
//--正文
Source Multiplayer Networking
較早的文章了,介紹了source引擎在多人對戰網路同步(尤其是用於fps遊戲)中的做法,在行業內影響了很多多人對戰遊戲的開發。
在了解了其中的技術和概念之後,對於玩家來說,就會知道為什麼fps遊戲對射的時候不要靜止,要來回跑,除了讓對方難以瞄準外,物理技術上也是如此哦
基本概念
這個圖可以說很好地表達了,客戶端和伺服器之間的關係。
- 伺服器一般以一定幀數(比如30幀,也可以更高)的速度tick,然後以一定頻率(一般低於tick的頻率)來發snapshot給客戶端
- 伺服器常常也buffer一些指令
- 客戶端以一定頻率發送input的指令(和tick幀數保持一致),然後本地buffer一定時間(比如100ms的伺服器傳過來的snapshot)
這兩點放在一起,就可以建立起一個邏輯基本正確的客戶端伺服器多人對戰系統了。
延時和體驗但是邏輯基本正確的系統是遠遠不夠的,對人對戰的體驗和單機打怪(我們認為這個是好的標準)之間的差異就來自延時。這裡的延時包括:對於移動以及射擊會有所不同,按照程序執行的順序- 按下滑鼠到網路packet發出--客戶端幀數越高越好
- 網路延時(ping)--延時最大頭
- 伺服器上面buffering的時間--可以根據重要性進行取捨
- 伺服器上面執行時間(幀數越高越低)
- 伺服器執行結果下行,又是一個網路延時(ping)--延時最大頭
- 客戶端buffering時間
- 客戶端顯示時間(敵人倒地飆血等等)
input prediction(預演)
所以,按照初始的客戶端伺服器邏輯,一槍開出去或者一個移動操作做出來,要經過這麼久才能有所反應,70ms延時,要150ms左右才能走完循環,這個體驗延遲感很強,就是有問題。所以引入一個input prediction的概念:就是不等伺服器返回確認,就立刻做出表現,移動,開槍射擊的彈道火花等等,然後在伺服器回包的時候做一個正確性驗證,不對的話就糾正。entity interpolation(平滑插值)然後平滑可以作為一個原則,加入到整個同步過程的方方面:- entity移動,伺服器發過來的是一個新的位置,那麼就通過一些插值(可以是線性,可以是曲線(走一個尋路))
- 本地糾正,如果伺服器驗證和本地預演不匹配,那麼一個瞬移就太糙了,可以走一個平滑的插值過去
lag compensation(延遲補償)
處理這個方法就是,開槍這種指令到伺服器上都是有時間戳的,然後伺服器會把敵人會退到開槍的這個瞬間,然後做計算命中,這樣邏輯就正確了。但是這個也不是絕對準確的,只能說是一個相對準確,因為這個回退位置不可能和你本地的時間完全一致,只能說是一個近似一致的。但是如果敵人是靜止的,那就完全一致了,所以一個靜止的敵人總是更容易被打中,即便技術上也是如此。優化這裡談的是fps遊戲,實際上這個系統可以用於大量的遊戲系統,比如mmo,然後體驗的優化就可以包括:- 預演做的更好:比如加上搓招,前搖等過程,儘可能把能預演的都做好,把「拙」藏好
- 降低延時:
- 網路路線選擇的更好
- 讓伺服器和客戶端tick的速度更高
- 可以的話減少buffering
- 可以的話減少移動插值的delay
死穴與邏輯衝突
在理解了工作原理之後,我們就知道有一些事情是不可避免的,比如:- 你看見敵人的瞬間就躲到掩體里,但是敵人還是爆了你的頭--這是有可能的,你的即時反應還沒有同步到伺服器上,而伺服器上計算命中是一個延遲補償的,所以本地雖然沒看到,但是還是被擊中了
- 移動的shooter比靜止的shooter有優勢,這裡是兩個原因
- 上面延遲補償部分提到了,移動的人對於另外一台的機器上的人來說,和伺服器上不會在像素級完全一致
- 另外就是有移動插值的存在,我們看動的物體總是有一定的延時,
所以fps遊戲的時候,兩邊對射,千萬別靜止站著,要左右跑,物理技術上就會比站著有優勢哦
推薦閱讀:
※Git筆記——基本功能(下)
※直接迭代序列要比通過索引迭代快?
※有哪些利用編程方法提高自己工作效率的例子?
※[10] Python條件判斷語句(一)
※【Kotlin填坑-02】使用高階函數後的when語句