前言
網絡延遲是客觀存在的,但網絡游戲行業已經積累了大量優質經驗,使用一些策略、技術手段在客戶端消除/隱藏掉延遲帶來的不便,以盡可能的掩蓋實際存在的延時,同時實現實時渲染,將用戶帶入快速的交互式實時游戲中,體驗完美的互動娛樂中。
這樣處理結果,稍高延遲的玩家也不會因為網絡不是那么好,也能夠很和諧的與其它網絡參差不及玩家一起游戲中。
雖然延時決定了實時游戲的最低反應時間,但最重要的是客戶端看起來要流暢。第一人稱設計游戲(FPS)可巧妙的化解與規避,最終在適合普遍用戶網絡環境中(200ms),實現實時快速互動游戲。
嗯,下面就是近期腦補結果。
網游P2P & CS結構
早先網游使用P2P網絡拓撲在玩家之間進行交換數據通信。但P2P模型引起的高延遲在FPS游戲中無法被很好掩蓋,所有玩家的延遲取決于當前玩家中延遲最爛的那個。好比木桶理論,低延遲網絡好的玩家會被高延遲壞網絡的玩家拖累。最終結果導致,所有玩家都不太開心了。但在局域網環境下,不會感覺到延遲帶來的問題。另,游戲邏輯大部分都集中在客戶端了,很難避免作弊行為。
C/S結構網游:
- C/S結構在服務器端跑所有的游戲邏輯和輸入響應,客戶端只需要渲染以及把自己需要一些狀態同步下來,把用戶輸入發給服務器端,然后顯示結果就可以了
- C/S結構網游最大優點就是把延遲從玩家之間最卡玩家的延遲改變為玩家和服務器連接的延遲,結果就是客戶端在帶寬上的要求也低了不少,因為只需要把輸入發給服務器端就以及接收服務器響應就夠了
- C/S結構網游雖然轉移了網絡延遲矛盾點,但現實網絡環境一樣會帶來較高的網絡延遲。客戶端每執行一次操作,都需要等待服務器端命令,那會用戶操作會造成操縱卡頓現象。如何解決呢,客戶端一般采用預測和插值等方式在渲染層隱藏網絡延遲
客戶端預測和插值
服務器可以允許某些情況下客戶端本地即時執行移動操作,這種方法可以稱為客戶端預測。
比如游戲中鍵盤控制角色行走,這個時候可以在很小的時間段(時間很短,比如1-3秒)內預測用戶行動軌跡(方向+加速度,角色行走結果),這部分的命令客戶端會全部發送到服務器端校驗正確與否(避免瞬間轉移等外掛)。但客戶端預測有時也不是百分百準確,需要服務器進行糾正(所謂服務器就是上帝,The sever is the man!)。糾正結果可能就是游戲角色行走軌跡和客戶端預測軌跡有所偏差,客戶端可以使用插值方式(粗略來講,就是角色在兩點之間移動渲染的方式)渲染游戲角色在游戲世界中的位置轉移平滑一些,避免游戲角色從一個位置瞬間拉回到另一個位置,讓人有些莫名其妙。
插值,有人也稱之為路徑補償,都是一回事。插值的方法會涉及到很多數學公式,線性插值、三次線性插值等,比如這篇文章所講到的插值那些事。
小結:客戶端預測,服務器端糾正,客戶端采用插值方式微調。
針對交互的一群玩家,網絡好壞層次不齊,游戲的一些操作效果可能需要”延遲補償“策略進行
延遲補償
延遲補償是游戲服務器端執行的一種策略,處理用戶命令回退到客戶端發送命令的準確時間(延遲導致),根據客戶端的具體情況進行修正,以犧牲游戲在傷害判定方面的真實感來彌補攻擊行為等方面真實感,本質上是一種折中選擇。
主要注意,延遲補償不是發生在客戶端。
關于延遲補償的一個例子:
- 在FPS游戲中,玩家A在10.5秒時向目標對象玩家B射擊并且擊中,射擊信息被打包發送(網絡延遲100毫秒),服務器于10.6秒收到,此時玩家B可能已跑到另外一個位置。
- 若服務器僅僅基于接收時刻(10.6秒)進行判斷,那么玩家B沒有收到傷害,或許可能會擊中玩家B后面緊跟的玩家C(100ms后玩家C完全由可能已處于玩家A的射擊目標位置)
- 為了彌補由于延遲造成的問題,服務器端需要引入“延遲補償”策略用于修正因延遲造成錯亂假象
- 服務器計算執行設計命令時間,然后找出當前世界10.5秒時刻玩家信息,根據射擊算法模擬得出是否命中判斷,以達到盡可能精確
若游戲延遲補償被禁用,那么就會有許多玩家抱怨自己明明打中了對方卻沒有造成任何傷害。。
有所得,有所失:但這對低延時玩家貌似有些不公平,移動速度快,可能已經跑到角落里并且已蹲在一個箱子后面隱藏起來時被對手擊中的錯覺(子彈無視掩體,玩家隔著墻被射擊),確實有些不樂意。
延遲補償,網絡高延遲的玩家有利,低延遲的玩家優勢可能會被降低(低延遲玩家利益受損),但對維護游戲世界的平衡還是有利的。
對時&閥值
客戶端和服務器需要對時,互相知道彼此延遲情況,比如云風定義的某個步驟:
客戶端發送一個本地時間量給服務器,服務收到包后,夾帶一個服務器時間返回給客戶端。當客戶端收到這個包后,可以估算出包在路程上經過的時間。同時把本地新時間夾帶進去,再次發送給服務器。服務器也可以進一步的了解響應時間。
C/S兩端通過類似步驟進行計算彼此延時/時差,同時會對實時同步設置一個閥值,比如對延遲低于10ms(0.01秒)的交互認為是即時同步發生,不會認為是延遲。
UDP或TCP
不同類型的游戲會鐘愛不同的協議呢,不一而足:
- 客戶端間歇性的發起無狀態的查詢,并且偶爾發生延遲是可以容忍,那么使用HTTP/HTTPS吧
- 客戶端和服務器都可以獨立發包,偶爾發生延遲可以容忍(比如:在線的紙牌游戲,許多MMO類的游戲),那么使用TCP長連接吧
- 客戶端和服務器都可以獨立發包,而且無法忍受延遲(比如:大多數的多人FPS動作類游戲Quake、CS等,以及一些MMO類游戲),那么使用UDP吧
TCP會認定丟包是因為本地帶寬不足導致(本地帶寬不足是丟包的一部分原因),但國內ISP可能會在自身機房網絡擁擠時丟棄數據包,這時候可能需要快速發包爭搶通道,而非TCP窗口收縮,UDP沒有TCP窗口收縮的負擔,可以很容易做到這一點。
要求實時性放在第一位的FPS游戲(eg:Quake,CS),廣域網一般采用UDP,因可容許有丟失數據包存在(另客戶端若等待一段時間中間丟包,可以通過插值等手段忽略掉),一旦檢測到可以快速發送,另不涉及到重發的時候UDP比TCP要快一點嘛。但會在UDP應用層面有所增加協議控制,比如ACK等。
很多時候協議混用,比如MMO客戶端也許首先使用HTTP去獲取上一次的更新內容, 重要信息如角色獲得的物品和經驗需要通過TCP傳輸,而周圍人物的動向、NPC移動、技能動畫指令等則可以使用UDP傳輸,雖然可能丟包,但影響不大。
小結
網游通過客戶端預測、插值和服務器端延遲補貼等,化解/消除用戶端網絡延遲造成的停頓。我們雖然可能沒有機會接觸游戲開發,學習跨界的優良經驗和實踐,說不準會對當前工作某些業務點的處理有所啟發呢。
本集由韓國宇航局贊助播出:我們要去遠方看看,還有什么是我們的思密達。 ------ 《萬萬沒想到》王大錘