How To Make Your Own Unity Deterministic Rollback Network

Danmaku Fighters 是一款快節奏的彈幕格鬥遊戲,使用 Rollback Network 讓玩家在與全世界的玩家對戰時可以有更滑順的網路體驗。


前言

格鬥遊戲為了更滑順的連線體驗,會使用 Rollback + Predict 將網路連線的延遲對玩家的體感影響降至最低。
我在製作 Danmaku Fighters 時,原先就是照著格鬥遊戲的標準在做的,自然我也打算為其加入順暢的連線體驗。
網路上已經有一些可自由使用的 Libraries 例如 GGPO,但由於遊戲的特殊性,我需要擁有更高的自由度,因此最後決定自己寫一套系統。
網路上能查到的相關資源相當有限,我希望在此留下資料能夠幫助到其他有類似需求的人,也希望這些資料可以提升更多獨立遊戲團隊製作連線動作遊戲的可能性。
若你成功閱讀到這篇文章,我相信您大概已經了解這些技術的內容與原理了,因此在這裡我只打算分享,如何將此技術實際運用至您的 Unity 遊戲專案內。
這篇文章內沒有太多程式碼,但會將所有您需要的細節都告訴您。


心理準備

為了實裝 Rollback 來達成流暢的網路對戰,一個很重要的關鍵字就是 Deterministic (確定性)。
Rollback 的原理建立在兩台電腦都必須在擁有一樣輸入的情況下,每一次都能得出同樣的結果才行。
意思是,您的遊戲中的任何一刻都應該要能夠被重現,且可以被錄製、複製、暫停、甚至是回朔,並且結果永遠不會改變。這將是您的終極目標。
為此,您的所有系統必須以此為前提去寫,這代表您無法使用 Unity Physics,包含 Trigger/Collider 也都無法使用,因為沒有方法可以確保雙方能在同樣的順序下觸發。您必須自己建立一套自己的物理系統。
在物理系統中,即使是一個微小的參數出了一點誤差,遊戲也極有可能在非常短暫的時間內就出現明顯的不同步情形,因此誠摯建議自行設計一套專用物理系統。 為了實現此一目標,以下是您需要完成的內容:
* 建立一個 Deterministic 物理系統,這包含了動能模擬、重力、碰撞系統判定等功能。
* 確保上述的物理系統在同樣的輸入情況下永遠都會得到同樣的結果,您可以使用錄製輸入的方法來驗證。
* 遊戲內的運算皆建立在 Fixed Time 上,確保雙方的運算速度一致,每一秒的運算次數都為固定值。不要用 deltaTime。
* 選定一個遊戲預計使用的連線方法,您可以自由選擇連線方法,但其邏輯概念都是一樣的。供您參考,我使用的是 Steamworks P2P。
* 一個您擁有完整控制權的遊戲運算順序管理系統,您需要設計一套運算順序來決定遊戲內各種邏輯、動作的運算先後順序。這是為了確定性,因為 Unity 內同層級的運算順序並不總是固定的。
* 接上題,您還需要讓運算系統可以在任何您需要的時候執行運算而非單純的固定速率運算,例如在同一個 Frame 內連續執行 5 次運算,因此您也無法使用一般的 Unity Messages 例如 Update 或 FixedUpdate。(至少在遊戲邏輯的主要系統上)
* 將連線的部分與實際遊戲系統接在一起,並實裝 Rollback + Predict 系統。


準備步驟

為了建立 Deterministic 物理系統,您會需要使用到 Soft Float。
我使用此 Soft Float Library:Soft Float Unity by Kimbatt
您可以自由選擇您想使用的 Soft Float Library,因為我們只單純需要 Soft Float,因此用哪一個都是一樣的。


Step 1. 建立物理系統