原文鏈接:Fast-Paced Multiplayer (Part III): Entity Interpolation
在系列的第1篇文章中,我們介紹了1種權威服務器的思想還有他在避免玩家做弊方面的優勢。但是直接使用這類技術會引發可玩性和響應性方面的問題。在第2篇文章中,我們提出了1種客戶端預測的方法來處理。
到現在為止我們提出了1套解決方案,能夠讓玩家在多人游戲中得到單人游戲般流暢的體驗,即便是在接入權威服務器并且有1定網絡延遲的情況下。
在這篇文章中,我們將會處應當有別的玩家連入相同的服務器的問題。
在前面的文章中,服務器的行動非常的簡單 - 讀取客戶真個輸入,更新游戲狀態,然后將結果返回給客戶端。當超過1個客戶端連接的時候,服務器的主循環邏輯就有點不1樣了。
在這類情況下,1些客戶端可能同時快速地發送輸入(比如按方向鍵,移動鼠標或單擊),每次收到客戶真個要求就更新游戲,然后再把救過進行廣播, 這樣會消耗大量的CPU和帶寬。
1種好的方式是將玩家的輸入壓到隊列中去而不馬上進行處理,服務器在1定的頻率上進行相對低頻率的更新,比方說沒秒10次。每次更新之間的時長稱為時間步長,在這里是100ms。在每次的更新迭代中,所有的未處理的輸入都今次那個處理(可能會比時間步長更小1些,來讓物理更可預測1些)然后新的游戲狀態就廣播給所有的客戶端。
總的來講,游戲世界的更新應當在1種可預測的頻率,獨立于玩家的輸入。
從玩家的角度看,這類方式還是像之前的方法1樣順滑 - 客戶真個預測獨立于更新的延遲,所以對可預測的狀態更新是沒有問題的。但是,由于游戲狀態以1種低頻率進行廣播,這將致使游戲看上去非常卡頓,多是100ms更新1次位置。
在客戶端2中看到的客戶端1的情況
根據你開發的游戲類型,可能有很多方法來處理,通常你的游戲實體越可預測,越好處理。
假定你在做1個賽車游戲。1輛快速開著的車是非常可預測的 - 假定他的速度是100m/s,那末1s以后,它應當大致在離起始點100m遠的位置。
為何是“大致”?由于在這1秒中以內,車可能加速1點,也可能減速1點,向右1點或向右1點 - 這里說的是1點點。由于車的機動性,車確當前位置總是依賴于它之前的位置,速度和時間。而不是玩家的輸入,換句話說,1輛快速運行的車沒法瞬間180度掉頭。
1個每秒更新10次的服務怎樣來處理呢?客戶端收到每輛車的速度和朝向以后,在接下來的100ms內,它不會遭到任何新的信息,但是客戶端還是要進行更新啊。最簡單的方法就是假定車在這100ms內,朝向和加速度都是常量,然后讓這輛車繼續運行,100ms以后,收到更新包以后,再對車的速度進行糾正。
糾正可能很大也可能很小,依賴于很多因素,如果玩家保持直線運行并且不改變車的速度,那末預測的結果和正式的位置是完全1致的。另外一方面,如果玩家撞到甚么東西,預測的位置就完全錯了。
有1點要提1下,航位推的算法可以利用在慢速的情況下 - 比如戰艦。其實這類算法最初就用在海上導航。
有許多情況航位推是沒法處理的 - 對玩家的方向和速度可以瞬間改變的都不行,比如3D射擊,玩家常常快速跑動,停下,快速轉向等,在這類情況下,航位推算法就非常無力了。由于位置和速度和前面的數據無關。
你可以選擇在接到服務器的要求的時候直接更新玩家的位置,而客戶端看到的就是網上其他的玩家每100ms跳1下,感覺會非常奇怪。
你現在具有的是每100ms由服務器傳送過來的權威數據,現在要做的是如何在這100ms內讓網絡角色看起來非常自然,解決問題的關鍵就是將網絡玩家顯示在過去的某個時刻。
假定你在t=1000收到位置信息,你已在t=900收到了1次位置信息,所以你知道玩家在t=900和t=1000的位置,所以在t=1000到t=1100之間,你只要顯示玩家t=900到t=1000的位置。這類方法,你所顯示的都是玩家的真實數據,只是有100ms的延遲。
客戶端2渲染的是客戶端1的角色過去的位置,利用插值來更新位置
用來插值的t=900和t=1000的數據依賴于游戲。插值通常都可以處理得很好。如果不是這類方法,你可能需要服務器發送更加詳細的移動信息了 - 比如更多的位置采樣點,或每10ms發送1次(你沒必要發10倍的數據 - 由于你發的微小的位移數據,在這類情況下數據的格式可以很好的優化1下)。
當使用這類技術的時候,每個玩家都和游戲世界有1點點不同步,由于每一個玩家看到自己的世界是當前的,但是其他的玩家都是過去的。但即便是快速的游戲,這100ms的延遲都不是那末明顯。
有1種情況除外 - 當你需要時間和空間的準確性的時候,比如1個玩家射擊另外一個玩家的時候,由于其他的玩家都是存在于過去的某個時候,你的瞄準實際上是有100ms的延遲的 - 也就是說,你設計的目標是100ms的某個目標! 這個問題我們下1篇會進行討論。
在權威服務器的環境中,有著不肯定的服務器更新和網絡延遲,在這類情況下你還要給玩家平滑的移動。在第2篇中,我們展現了1種客戶端預測和服務器調和的技術,來實現實時的角色控制,這樣的方案讓玩家能夠得到即時的反饋,移除致命的延遲。
其他玩家的同步還是1個問題,但是,在這篇文章中,我們提出了兩種解決方案。
第1種是航位推技術,這類摹擬需要entity的位置能夠通過前1個時候的位置,速度,加速度來推算出來,當不滿足這類情況的時候,航位推就沒用了。
第2種是插值技術,不預測將來的位置,只是使用服務器傳來的數據,這類就會造成顯示的entity總是過去的某個時刻。最后的結果就是玩家的角色總是當前時刻,而其他看到的entity都是過去的某個時刻,這類情況可以產生1種難以置信的無縫體驗。
但是,當游戲需要高速離散的準確性的時候,比如射擊或移動物體,美景就幻滅了:你看其他玩家的位置和服務器的位置不1致,別的玩家看你的位置也不是正確的,這樣爆頭就不可能產生了!很多游戲都有爆頭這1說,我們將在下面的文章中來討論這個問題。
下一篇 關于socket