Note
目前還算是比較粗糙的想法展示。到現在大概寫了 4 次左右,近期的新實作有些心得了,還沒理解到可以完美表達的程度,先把我的想法寫下來。
為什麼不使用原生的 Rigidbody?
Rigidbody 的功能,是用來模擬物體在真實世界的移動、摩擦與碰撞反應。實際上是轉接了 PhysX 與 Box2D 這種傳統物理引擎。但遊戲並不是要模擬真實世界,特別是平台類型有各種完全不符合內建物理系統設計的需求,例如:斜坡移動、碰撞忽略、碰撞扭曲、邊緣跳躍……等等。另外因為內建物裡的時序和 API 的設計,必須依賴在引擎,也不符合通用需求。
有時候也還是可以硬著頭用內建物理系統來製作,但如果要講求遊戲邏輯正確性的時候,寫起來就需要幹一些像是在 hack 物理參數的事情,我覺得只是用不適合的工具在找自己麻煩。
不錯的入門參考資料
物理計算
- 2D Platformer Controller (Unity 5) - YouTube 蠻完整的教學,但是程式碼有很多 edge case 沒考量到,結果來說他的程式碼是完全不能抄的,但是做為演算法的入門參考還不錯。
- Corgi Engine - 2D + 2.5D Platformer | Systems | Unity Asset Store Unity Asset Store 上最大最貴的平台控制套件。(夾雜了一堆跟平台控制核心無關的功能。)我還蠻喜歡他們 Demo 的呈現,真的是蠻吸引人的。
Game Feel
- Celeste & Forgiveness Celeste 各種改善操作體驗的做法。
- Platformer Toolkit by Game Maker's Toolkit 很棒的互動式教學,可以透過前後差異,來了解改善手感的重要性。不過這些功能在大部份都算在狀態處理層。他的程式碼還是使用 Rigidbody 在操作,因為他的物理空間還是用比較基本的方形物件組成的。
- 從移動和跳躍開始,做好 2D 平台跳躍遊戲的角色控制 BB001 | PE 工具箱 Bionic Bay 的開發者整理的內容。繁體中文圈為數不多的好文章。
基本前提
使用 Collider 與 Raycast
我們只是不想使用內建物理引擎的計算邏輯,但 Collider 和 Raycast 還是可以用,因為它們只是資料和探針。我們的作法只是把 Unity 當作物理空間的資料,然後轉給我們自己的物理計算(反正 Rigidbody 內部也是這樣做的),同時關卡設計師也可以保留對 Unity 引擎的使用認知。
可測試性
畢竟是數學計算,還有浮點數誤差問題,會出現太多沒注意到的盲點,寫測試比較容易追蹤。也因此需要特別把移動計算的部分拆出來變成可獨立測試的區塊。
浮點數誤差問題
數學計算上常常會碰到浮點數誤差問題,所以我們需要在方塊外圍設定一層安全區域,通常會用 skin 這個詞來代表這個外圍空間。
不適合套件化
每個遊戲所需要的功能不同,細節也不同,所以很難真的有絕對泛用的套件,所以必要的時候還是得自己寫適合的控制器。
整體架構概念
玩家輸入與狀態控制層
- 玩家輸入指的是,呃……玩家輸入。
- 狀態控制指的是,根據上一幀的角色狀態與當前玩家輸入,計算出這一幀角色狀態的邏輯。通常就是所謂的商業邏輯。例如:速度與加速度、碰撞塊尺寸、其它參數。
Note
玩家輸入和狀態控制,在比較簡單的情況可以寫在同一個腳本。但碰到這些狀況就會想拆開:
- AI 輸入:玩家輸入用的是
InputSystem,AI 輸入用的是程式邏輯。然後你一定會希望這些輸入可以共用同一個狀態控制邏輯。- 控制幀率:特別是網路遊戲,由於輸入幀率會與邏輯幀率不一致,會需要特別緩存輸入。
速度說穿了只是一個參數,數值怎麼變化是由商業邏輯決定的,不是物理計算器。物理計算器只負責由使用者給定的位置、速度與其它參數,透過 raycast 探測物理空間,來計算位移向量。
例如:
- 單純的角色奔跑,只是加減速的做法差異。
- 在冰面地板滑冰,只是加速度和轉向做法差異。
- 跳躍的上升和下降的重力,可能也有做法差異。
- 二段跳甚至根本跟物理系統沒有關係。
- 爬牆或滑牆,只是重力參數不同。
但這些通常都不會改變內部物理碰到障礙物要位移時的計算邏輯。
世界探針層
這個層級負責處理實際的 raycast。
把 raycast 和物理計算拆開的好處是:
- 解耦與可測試性:物理計算可以與
Physics/Physics2D解耦,也可以在測試碼偽造物理世界,方便檢查數學計算結果。 - 空間修改性:物理計算實際上並不知道世界長什麼樣子,只負責根據 raycast 的結果來計算,這樣角色、空間或重力的旋轉,就可以與物理計算脫鉤。世界探針也可以自己決定要忽略那些資訊。例如:剛從單向平台 (one-way platform) 落下時,世界就不應該偵測到那個碰撞塊。
物理計算層
核心程式碼。根據位置、位移與其它計算參數,透過封裝的世界探針,獲取世界資訊,來計算實際的位移向量。
修改商業邏輯時,物理計算其實很少出現改動需求,通常都是去改動狀態控制邏輯,然後其次是世界探針。所以把比較複雜的物理計算邏輯單獨拆出來,其實也符合單一職責原則 (SRP)。
下一篇
Note
TODO