這個篇文章的主要目標是給予你一個關於在Unity中簡單的優化物理系統
我的遊戲物理系統有什麼錯誤嗎?
怎麼去處理遊戲物理系統?
Unity 物理系統有什麼缺陷嗎?
Unity 是怎樣處理物理系統的?
我在 Unity 物理系統上做了什麼控制?
在我開始使用遊戲物理系統之前我應該關心什麼事情?
我應該在時候避免使用物理系統?
我看到了幀速率在下降,這是否是物理系統導致的?
當涉及到物理系統時,便會有以上這些問題,或許你會有更多像上面類似的問題。
是的,是的,我知道!我們全怪那個平果,它爲什麼要在那一天降臨到牛頓的頭上?爲什麼呢,上帝?
物理學也許不是每個人最愛的科目,但是物理學在遊戲開發行業中真的是一個非常重要的角色。
想象一種情況,在緊要關頭你最終決定提出做一個大事情。一個讓人矚目的,一個使用逼真的物理和圖像的大遊戲。
設計已經創建出來,架構已經完成,一切看上去似乎已經準備就緒。但是你最終坐了下來,開始在最棘手的部分上工作,“物理系統”!!
此時,似乎所以東西都崩潰了;你無意中看到了很低的FPS,奇怪的移動,碰撞器/觸發器 出現了問題,高CPU使用率等等。
不恰當或者不正確的使用物理系統可能會把一些遊戲玩家嚇跑。這不只是關於不恰當的使用物理系統的問題了;這是關於一個遊戲可玩性高不高的問題了。
這些都是不容易解決的問題。物理系統是遊戲開發過程中最困難,也是最重要的一部份,這是無法避免的!!
人們可能會說:“好的物理系統需要一個超快的CPU!”。
但是,請相信我,這句話不一定都是對的。多數情況下,可以通過由淺入深進入Unity的海洋中學習Unity 的物理系統是怎樣工作的,以便我們實現更好的物理系統。
在我還是一個程序小鮮肉的時候,我便要處理100多個與物理相關的事情。這讓我花了近一年的時間記錄下了處理物理相關的關鍵點。
因此,我決定寫這篇文章。幫助大家跳躍這個學習階段的痛苦,成爲一個專業的物理系統開發者。
我不打算講關於物理系統在Unity中是如何工作的,然而我將會在怎麼優化你的物理系統中列出技巧和要點。所以,如果你是一個新手,我建議你先去大概瞭解一下Unity 物理系統。
物理學是一個非常非常龐大的、廣泛的概念,我決定分成不同的部分,儘可能做到簡單。
接下來,這是一個漫長有趣的過程,請你趕緊繫好你的安全帶,讓我們開始吧!
降低固定時間步(Fixed Timestep)
在Unity文檔的說明如下:
“一個不受幀速率影響的時間間隔,用於指定在 FixedUpdate() 函數中執行物理計算每一幀的時間間隔”
默認值爲 0.02(每秒),這顯示了每 20ms(毫秒)物理更新將會被執行一次。所有 FixedUpdate() 也會每20ms調用一次。
你需要不停的改變這個值,以獲得理想的效果。
例如:
“如果你打算做一個簡單的卡牌遊戲,這不需要使用太多的物理系統。然而最好減少調用物理引擎的次數。但是這操作要很細心一點;如果你減少過多的物理引擎調用的次數,你也許不會得到你想要的物理效果。”
讓我們通過下面的案例更好的理解 Fixed Timestep 吧!
步驟 1) 創建 3-4 個 球體。讓他們保持一些距離:
步驟 2)創建物理材質(通過在Assest文件夾中按下右鍵->Create->Phycics Material),並且設置摩擦係數(Friction Amount)的數值爲 0 ,然後設置彈力系數(Bounciness)爲 1,再設置彈力混合(Bounce combine)爲最大值:
步驟 3)將該物理材質添加到球體碰撞器的物理材質卡槽中去:
步驟 4)爲球體添加剛體組件(這將意味着此物體時物理對象):
步驟 5)創建一個平面,並且爲其創建一個物理材質(先使用默認值),添加到平面上:
步驟 6)讓創建的球體位於平面的上方,並且設置球體的重力選項盒爲勾選狀態。
步驟 7)點擊 Play 按鈕,並且查看一下結果。
這個球在做一下一上的動作。(不好意思,污了一下下。)
那麼,這與固定時間步(Fixed Time Step)有什麼關係呢?
上面只是一個簡單的設置,現在我讓我們開始玩耍 Fixed Time Step 的值吧!
找到 Edit>>Project Settings >> Time,在那裏,你能找到 Fixed Time Step ,它的默認值爲 0.02 (正如我之前提到的那樣)。
現在讓我們設置它爲 0.1,然後按下 Play 按鈕開始遊戲。
你有發現有什麼不同嗎?
首先你會注意到,這些球的運動非常的慢。
然後,你會看到球體穿過了平面而不是反彈回來。
你會問爲什麼?(不需要彈跳如此的快呀!啊哈哈)
好的,如果你設置 Fixed Time Step 爲 0.1,這就意味着物理更新將在每100ms(毫秒)執行一次,這很快就會注意到,將無法檢測到碰撞。
這表明,過多的降低 Fixed Time Step 的也是不恰當的。現在讓我們改變 Fixed Time Step
的值爲一個更爲實際可行的值 0.03 - 0.04。(具體根據球體的需要來定)
現在,如果你開始遊戲,你不會看到任何改變。只要看上去還行,那就OK。如果你細心的檢查一番,物理碰撞檢測會有一點點不同的。
看看下面的圖片:
如果你不能跟上步驟來,那麼請你參考一下Unity的官方文檔。適當的理解 Unity 物理引擎是必須的。
物理碰撞檢測會有點延遲,只會在當前幀結束之後才反彈回去。
這在你遊戲處於正常FPS下可能觀察不到,但是這可能會影響到物理效果。但只要你的需要滿足了,這也是沒什麼關係的。
這將有什麼幫助呢?
任何時候你從物理計算中節省下來的計算資源,都可以讓給渲染和其他計算密集的處理,所以就可以讓你的遊戲更加出衆。
通過設置 Maximum Allowed Timestep 在物理系統中保持檢查!
在Unity文檔中的定義如下:
“一個不受幀速率影響的時間間隔,當幀率爲最低峯值的時候,物理計算和 FixedUpdate() 事件將不會被執行”
那麼,這意味着什麼呢?
讓我們先在正常的遊戲下,去理解它(Maximum Allowed Timestep)。
如果你的遊戲在運行的時候能保持在 60 FPS,這就意味着每一幀會執行 0.01666秒。意味着每一幀需要花費 16.7ms(毫秒)。
現在,讓我們把 Fixed TimeStep 設置爲 0.01,這表明物理更新將每 10ms 執行一次。
這表明,在每一幀中至少會調用一次物理更新,因爲 10ms<16.7ms. 現在讓我們假設由於某種原因幀率降低到了 30 FPS。
那麼,每一幀將會執行 0.0333秒(也就是33.3ms) 。也就意味着在每一幀中會調用3次物理更新(因爲一次物理更新花費10ms)。這意味着如果幀率繼續下降,每幀內的物理調用還會更多。
這將會導致程序崩潰。爲了解決這個問題,下面引入 Maximum Allowed TimeStep。
它的默認值爲 33ms(可能是作者搞錯了,明明就是0.33333秒 = 333。33ms啊)。正如 Maximum Allowed TimeStep 定義:每當物理更新超過指定的時間,物理更新將會停止。因此,這便爲其他進程節約了資源。
在我們的案例中,如果每一幀執行時間增加到 40ms,這將會調用更多的物理更新。
但是現在我們設置 Maximum Allowed TimeStep 爲 0.033,也就是33ms ,物理更新將會在 33ms 後停止調用,也就是執行3次物理更新後,便會停止調用,儘管每幀的執行時間超過 50ms 也會如此。
因此爲其他沉重的進程節省下一些資源。
這聽起來非常的棒,不是嗎?
但還是有會一些限制的負面影響。每當發生性能故障,動畫和物理便會放慢(意味着畫面卡頓,延遲)。
因此,要牢記Maximum Allowed TimeStep 同樣是一個重要的因素,如果使用得當,將會得到非常好的效果。
總是有 1-1-1 的比例
放大一個沒有物理的對象是沒有問題的(就是沒有與物理相關組件的物體對象),但是當一個物體時一個物理對象時,我建議你不要對該物體進行縮放。縮放會導致奇怪的碰撞檢測,也會影響到物體的下落方式。
例如:
還有一個選項是調整重力加速度的值讓他看起來變得正常,但是這不是最正確的做法。正確的做法應該是保持使用1-1-1的縮放比例,因爲Unity的物理引擎在這種情況下工作的最佳。
給你的對象設置恰當的質量
和縮放一樣,質量也需要保持精確。
讓一架飛機的質量爲 1kg 正確嗎?
如果你考慮到度量系統準則,Unity的 1 個單位等於 1 kg 質量。同樣的,Unity的 物理系統是無量綱的。但是,如果你假定 Unity 的一個單位的長度爲米,那麼,一個質量的單位爲 kg。
你可以得到更完美的結果。並且,Unity在努力解決高浮點數問題,所以儘量削減取值範圍是比較理想的解決方案。
這意味着,如果假設你的飛機重 1kg ,那麼你的輪子必然不會超過 1/1000 kg。
儘可能避免使用網格碰撞器(Mesh Collider)
對任何物理引擎來說,基於網格的碰撞檢測都比原始的碰撞檢測需要更多的計算量,這是一個事實。Unity在內部使用了 Nvidia 的 PhysX,因此這是沒有什麼不同的。
一般來說,
“對於不同碰撞檢測的相對成本從高到低的排序爲:三角形網格、凸包(具體可以百度百科)、膠囊體、球體、盒子(六面體)、平面、點”
通常,網格碰撞器(Mesh Collider)被標記爲凸包(也建議大家這麼標記),它將被限制到255個三角形。只有在兩個網格碰撞器被標記爲凸面(Covex)時才能相互發生碰撞檢測。
在 Unity 文檔中的說明:
”使用網格碰撞器時會有一些限制。沒有標記爲凸面(Convex)的網格碰撞器只支持在一個沒有剛體組件的遊戲對象(GameObjecet)上發生碰撞,如果你想要在一個剛體上使用一個網格碰撞器,這必須要標記爲凸面“
對於複雜的網格,你通常可以使用 Blender(小巧的建模軟件)或者其他工具來將它們分解成一些小部分。然後可以用傳統碰撞器直接替換掉這些小部分的網格。
我希望我已經給你一個確切的優化描述,但是不幸的是,每個網格都是不一樣的,對於我給出一個確切的描述是非常困難的。
後續很快就會來到
總結:該篇文章大體講了一下幾個關鍵字:Fixed TimeStep、Maximum Allowed TimeStep、Mesh Collider、Convex。
這些東西都能在官網組件手冊中找到一些詳細的說明,如果看不懂該文章所說的內容,還請大家自行去看一看官網的組件手冊(還記得我給你說的 Unity 聖典嗎)
轉載自公衆號:Unity牆外的世界