遊戲中渲染層實體如何平滑的做插值?

在網路遊戲實現前後端同步的模型中,很多對實時性要求很高的類型的遊戲往往需要前端先進行預測,然後將按鍵等輸入發往伺服器,伺服器進行滯後的模擬,然後前端根據服務端的計算結果來進行校正(這個校正請求可能由服務端發起,或前端自己進行),這時前端由於領先伺服器,在得到服務端一個「過去」時間段的正確結果來「回溯」計算到客戶端當前時間,像守望先鋒或是王者榮耀分享的網路同步方案中都有這樣的模型。

但是由於這個回滾操作的存在,如果渲染層和邏輯層是同步的,回滾的結果往往跟當前的計算結果差距很大,這樣在表現上回很不平滑,拉扯感很明顯,會造成卡頓的體驗。所以很多都是將渲染層和邏輯層進行分離。

問題在於將渲染層實體向邏輯層進行插值的平滑演算法一般是如何實現的?簡單的線性平滑內插外插在應對大誤差的情況表現的貌似並不好,特別是針對有物理引擎剛體實體時,回滾操作之後,邏輯層剛體的位置線速度角速度變化都很大,這時候如何才能使得渲染層平滑的表現?看到hermite插值的插值目標點貌似是不改變的,但是對於實際計算中,邏輯點的位置速度等屬性也是一直在變化的,這樣渲染層的插值如何計算?

============================================

《守望先鋒》架構設計與網路同步 -- GDC2017 精品分享實錄,這邊分享中網路同步部分的 「預測錯誤」,「和解」(reconcile)部分就是所說的前端回滾操作


主要基於 Source 引擎的這篇文章 Source Multiplayer Networking 作答。如果和題主查閱的相關資料或者題主對同步邏輯的理解有偏差,希望指正。

簡單的線性平滑內插外插在應對大誤差的情況表現的貌似並不好,特別是針對有物理引擎剛體實體時

這裡的「大誤差」具體指的是什麼?是指變動特別劇烈嗎?物理引擎的計算似乎不會帶來很大的「誤差」。

回滾操作之後,邏輯層剛體的位置線速度角速度變化都很大,這時候如何才能使得渲染層平滑的表現?

在客戶端不會進行回滾,回滾的操作只是在服務端進行的。客戶端進行的操作只是基於伺服器發送的幀同步包進行插值模擬。並且,回滾操作本身只是一個臨時的操作,主要用來進行關鍵的操作判定邏輯(e.g. 玩家的此次射擊是否擊中另一個玩家?),不會對服務端實際的世界狀態造成影響。

具體的來說,在幀同步演算法下,客戶端在每一個渲染幀所做的事:

  1. 根據當前時間戳,拿到渲染時間,再根據渲染時間拿到對應插值區間的兩個關鍵幀(關鍵幀是伺服器同步過來的)
  2. 計算出當前幀根據在這兩個關鍵幀之間的時間位置,進行插值
  3. 如果渲染時間超出了最後一個關鍵幀對應的時間,則基於最後的關鍵幀進行外插值

題主所說的回滾發生在伺服器端,僅當服務端拿到客戶端發送的輸入幀,並且要進行對應的邏輯判定時。此時:

  1. 伺服器通過客戶端的時間戳計算出其當時的渲染時間
  2. 伺服器拿到那個渲染時間對應的兩個關鍵幀,備份當前所有實體的位置並進行和客戶端同樣的插值
  3. 在服務端插值到同樣的時間點後,執行相關判定邏輯
  4. 相關判定邏輯執行完成後,復原所有實體的位置

所以,至少這個意義上的回滾邏輯和客戶端沒啥關係。如果題主的意思是在客戶端和伺服器判定邏輯不一致造成的瞬移等情況,這個是進行關鍵幀同步再插值以後出現的自然現象,也不會有一個明確的邏輯去進行回滾。


我大概理解你想問什麼,插值只能保證兩點之間的變化平滑,但你想要的結果是客戶端根據服務端傳回的結果矯正極大偏差時不產生類似快動作的突兀感,這個靠插值是無能為力的,因為對於「丟失」的這段時間裡的內容要麼快放要麼跳過,還沒想到更好的處理辦法,否則網路遊戲也不用對網路延時有較高的要求了。


推薦閱讀:

Google旗下機器人Atlas步行演算法再升級,成功挑戰困難地形
圖解嵌入式系統開發之演算法篇:冒泡排序
5/7 演算法題詳解:Compute all mnemonics for a phone number 從一個手機號碼得到所有可能的字元組合
推薦 | 樸素貝葉斯演算法基於R語言的案例實現

TAG:演算法 | 計算機網路 | 計算機圖形學 | 物理引擎 |