5_物理模塊
物理模塊相關的知識點

物理和時間
物理模塊的更新是在FixedUpdate()中進行的,默認為0.02秒更新一次(每秒50次),這個時間被稱為步長
Unity的更新循環(huán)是以每幀更新的方式進行的,在每一幀中,首先執(zhí)行物理模塊的更新,然后再進行渲染和其它邏輯的處理,在更新時會檢查是否需要執(zhí)行FixedUpdate()
如果自上次固定更新以來經(jīng)過的時間太短(小于0.02秒),則跳過當前的固定更新

最大允許的時間步長
如果自上次固定更新以來經(jīng)過了很長時間,那么固定更新將持續(xù)計算,直到趕上當前時間
比如上一幀花了100毫秒進行渲染,那么物理引擎需要執(zhí)行5次FixedUpdate(),以盡量保證物理模塊的穩(wěn)定,但由于這期間渲染模塊一直沒有更新,等到FixedUpdate()執(zhí)行完后更新渲染畫面,物體就會有瞬移了一段距離的感覺
另一種情況是執(zhí)行一次FixedUpdate()花的時間超過了一個固定時長(0.02秒),這樣會導致物理模塊永遠無法擺脫固定的更新循環(huán),為了防止這樣的情況發(fā)生,Unity會設置最長執(zhí)行時間,來限制在FixedUpdate()階段所花的時間,如果處理時間太長,他將停止并放棄進一步的處理,直到渲染和其它邏輯走完后再進行FixedUpdate()的調(diào)用
運行時修改物理組件
Rigidbody組件中的方法更新頻率與物理模塊更新頻率緊密耦合,因此如果要修改Rigidbody中的參數(shù)最好在FixedUpdate中進行修改,如果在Update中修改可能會導致在不同設備上運行的結果不一致
靜態(tài)碰撞器和動態(tài)碰撞器
動態(tài)碰撞意味著這個這個物體包含了Rigidbody和碰撞器組件,此時這個物體會對其它物體的碰撞做出反應
靜態(tài)碰撞則是沒有附加Rigidbody,只包含了碰撞器組件的物體,這樣的物體會與其它物體發(fā)生碰撞,但本身不會有任何反應
碰撞檢測
Rigidbody有4種類型的碰撞檢測
Discrete(離散):在每次FixedUpdate調(diào)用時檢測是否碰撞
Continuous(連續(xù)):對物體運行的軌跡進行插值,以檢測在FixedUpdate方法調(diào)用之間產(chǎn)生的碰撞
ContinuousDynamic(連續(xù)動態(tài)):與Continuous相同,但主要用于對多個動態(tài)物體的連續(xù)碰撞檢測
ContinuousSpeculative(連續(xù)推測):通過物體在離散時的運動間隔內(nèi)推算可能發(fā)生的碰撞
性能開銷:Discrete < ContinuousSpeculative < Continuous < ContinuousDynamic
檢測準確性:ContinuousDynamic < ContinuousSpeculative< Continuous<?Discrete
碰撞矩陣
物理引擎具有一個碰撞矩陣,這個矩陣定義允許哪些對象之間會發(fā)生碰撞
可以通過Editor → Project Setting → Physics/Physics2D → Layer CollisionMatrix 訪問

Rigidbody激活和休眠狀態(tài)
當Rigidbody處于休眠狀態(tài)時,在FixedUpdate更新過程中,物理模塊就不會對其進行處理,直到它被外力或碰撞事件喚醒
判斷一個物體是否會處于休眠狀態(tài)是根據(jù)物體的移動速度和角速度確定
可以通過Editor → Project Setting → Physics → SleepThreshold 修改
SleepThreshold指的是當移動速度和角速度,都低于該值時就進入休眠模式

使用物理模塊的一些注意點
縮放:盡可能的使游戲世界中所有物理物體的縮放接近(1,1,1),物體大小應該反應真實世界的物體尺度,因為縮放過大會導致物體的移動速度比預期慢得多,如果物體放大了5倍那么重力也會減弱5倍
位置:保證所有對象盡量接近世界原點(0,0,0),將具有更好的浮點數(shù)精度,提高模擬的一致性
質(zhì)量:質(zhì)量以浮點數(shù)的形式儲存在剛體組件的質(zhì)量屬性下,不同物體之間的質(zhì)量應該控制在合適范圍內(nèi),這樣在碰撞時才不會因為突然出現(xiàn)的巨大動量差導致物體的速度瞬間出現(xiàn)很大的改變,導致一些不穩(wěn)定的物理現(xiàn)象發(fā)生
優(yōu)化碰撞矩陣:當兩個物體之間發(fā)生碰撞時,Unity會首先檢查它們所屬的Layer是否允許碰撞,這是通過檢查碰撞矩陣來實現(xiàn)的,關閉一些層級的碰撞雖然不會有性能的提升,但是可以減少一些因設置錯誤,而引起的問題

優(yōu)化物理模塊

使用合理的碰撞檢測類型
上文提到過Rigidbody有4種類型的碰撞檢測,檢測精度高的開銷也高,但不是所有情況都需要這么高的精度,選擇合適的就行
Contact數(shù)量是否合理
在性能分析器的物理模塊中可以統(tǒng)計當前正在發(fā)生碰撞的物體數(shù)量,由于碰撞后剛體組件需要計算被力作用的結果,因此當正在發(fā)生碰撞的物體很多時cpu就需要花費更多時間去計算,如果場景中看起來沒有物體發(fā)生碰撞,但是Contact數(shù)量又很多時,就需要檢查當前時間段是不是某個物體的碰撞框大小設置出了問題,可以使用代碼檢測主要是哪個物體產(chǎn)生了這么多碰撞


