Unity-連續(xù)碰撞檢測 (CCD)
CCD 確保快速移動的物體與對象碰撞,而不會穿過這些對象。Unity 提供以下 CCD 方法:
基于掃掠的 CCD
推斷性 CCD
要使用基于掃掠的 CCD,請在 Inspector 窗口中選擇一個剛體 (RigidBody),并將?Collision Detection?設(shè)置為?Continuous?或?Continuous Dynamic。要使用推斷性 CCD,請將?Collision Detection?設(shè)置為?Continuous Speculative。
基于掃掠的 CCD
基于掃掠的 CCD 采用撞擊時間 (TOI) 算法,通過掃掠對象的前向軌跡來計算對象的潛在碰撞(采用對象的當(dāng)前速度)。如果沿對象移動方向有接觸,該算法會計算撞擊時間并移動對象直至達(dá)到該時間。該算法可從該時間開始執(zhí)行子步驟,即計算 TOI 之后的速度,然后重新掃掠,代價是需要經(jīng)歷更多的 CPU 周期。
然而,因為此方法依賴于線性掃掠,所以會忽略物體的角運動,這在對象迅速旋轉(zhuǎn)時會引起穿隧效應(yīng)。例如,彈球機上的彈球桿固定在一端,圍繞一個固定點旋轉(zhuǎn)。彈球桿只做角運動,不做線性運動。因此,很容易打不中彈球:

此方法的另一個問題是性能問題。如果附近有大量啟用 CCD 的高速對象,CCD 的開銷將由于進(jìn)行額外的掃掠而很快增加,因此物理引擎不得不執(zhí)行更多的 CCD 子步驟。
推斷性 CCD
推斷性 CCD 的工作原理是基于對象的線性運動和角運動增大一個對象的粗篩階段軸對齊最小包圍盒 (AABB)。該算法是一種推測性的算法,因為會選取下一物理步驟中的所有潛在觸點。然后將所有觸點送入解算器,因此可確保滿足所有的觸點約束,使對象不會穿過任何碰撞。
下圖顯示了從?t0?開始移動的球體如何獲得預(yù)期的?t1?位置(如果其路徑中沒有墻)。通過使用目標(biāo)姿勢將 AABB 擴大,推測性算法選取與?n1?和?n2?法線之間的兩個觸點。然后,該算法告訴解算器遵循這些觸點,使球體不會穿過墻壁。

基于當(dāng)前速度并擴大的 AABB 有助于檢測沿運動軌跡的所有潛在觸點,使解算器能夠防止對象穿過去。
推測性 CCD 的成本通常低于基于掃掠的方法,因為只在碰撞檢測階段(而不在求解和積分階段)計算觸點。此外,由于推測性 CCD 根據(jù)對象的線性運動和角運動來擴展粗篩階段 AABB,因此能發(fā)現(xiàn)基于掃掠的 CCD 可能遺漏的觸點。

但是,推測性 CCD 可能會導(dǎo)致幽靈碰撞;在這種碰撞中,對象的運動受到推測性觸點的影響,而這是不應(yīng)發(fā)生的。這是因為推測性 CCD 根據(jù)最近點算法收集所有潛在觸點,所以觸點法線不太準(zhǔn)確。這通常會使高速對象沿著細(xì)分的碰撞特征滑動并跳起來,但不應(yīng)該這樣。例如,下圖中,球體從?t0?開始向右水平移動,積分后的預(yù)測位置為?t1。擴大后的 AABB 與框形?b0?和?b1?重疊,而 CCD 在?c0?和?c1?產(chǎn)生兩個推測性觸點。由于推測性 CCD 使用最近點算法來生成觸點,__c0__ 具有非常傾斜的法線,因此解算器會將其視作斜坡。

這種非常傾斜的法線導(dǎo)致?t1?在積分后向上跳動,而不是筆直向前移動:

推測性 CCD 還可能導(dǎo)致發(fā)生穿隧,因為只會在碰撞檢測階段計算推測性觸點。在觸點求解過程中,如果一個對象從解算器獲得太多能量,在積分后,其最終位置可能在初始擴大的 AABB 之外。如果在緊鄰 AABB 的外部發(fā)生碰撞,對象會從右邊穿出。
例如,下圖顯示了球體從?t0?向左移動,而球桿順時針旋轉(zhuǎn)。如果球體從撞擊中獲得太多能量,最終可能離開擴大的 AABB(紅點矩形),落在?t1?處。如果在緊鄰 AABB 的外部發(fā)生碰撞(如下面的藍(lán)色框所示),球體最終可能會從右邊穿出。這是因為解算器只計算擴大的 AABB 的內(nèi)部觸點,在求解和積分階段不會執(zhí)行碰撞檢測。
