最適な衝突判定を即選択。Collision Detection 早見表【Unity 2018.3 以降】

こんにちは!バーチャルキャストクライアント開発の江口です。最近は主にバーチャルキャストのバグ修正を担当しています。以前、オブジェクトが床を貫通してしまう不具合を修正したときに、Rigidbody の Collision Detection (衝突判定) のモード選びで悩み、多くの時間を使ってしまいました。Unity 2018.3 以降で使用できる4つの Collision Detection モードがまとめて解説されている日本語ページを見つけられなかったので、この機会に一発で適切な Collision Detection を選べるフローチャートを作成しました。

Collision Detection 早見表

各 Collision Detection の解説

Discrete モード

Discrete モードは Rigidbody コンポーネントを追加した時にデフォルトで選ばれている衝突判定モードです。最も処理が軽い衝突判定です。しかし、このモードには大きな欠点があります。それはフレームとフレームの間に起きるオブジェクト同士の衝突が考慮されないという点です。つまり、弾丸のように高速で移動するオブジェクトに使用すると、薄い壁などを貫通してしまうことになります。

この動画では弾丸オブジェクトの Collision Detection が Discrete に設定されています。

 

弾速が遅めに設定されているので壁を貫通してしまうことはありません。しかし、弾速を速くした場合はどうでしょう...

 

弾速が速く、弾丸オブジェクトと壁オブジェクトが重なり合うフレームが存在しないため、弾が貫通してしまっています。このことから、Discrete は移動速度が遅いオブジェクトにのみ使用できるということが分かります。

Point:オブジェクトの移動速度が遅い場合のみ Discrete を使う。

Continuous モード

この貫通問題を解消するのが Continuous (連続) モードです。Continuous モードではオブジェクトの進行方向にある他のオブジェクトを予め取得して衝突する可能性があるかどうかを判断するため、移動速度が速くても貫通しません。Unity には3種類の Continuous モードがあり (Continuous、Continuous Dynamic、Continuous Speculative)、そのうち最も動作が軽いのが Continuous モードです。

Continuous モードでは静的オブジェクトに対する衝突のみが検知されます。静的オブジェクトとはゲームのステージや壁など、全く動かないオブジェクトで、Rigidbody コンポーネントがないものです。先ほどの弾丸の Collision Detection を Continuous に変更すると、このような挙動になります。

 

意図通り、弾丸が壁に跳ね返されていることがわかります。しかし、もしこの壁が動く壁、つまり Rigidbody コンポーネントを持つ動的オブジェクトだったらどうなるでしょう?

 

このように、Continuous モードでは動的オブジェクトは貫通してしまいます。時々、衝突判定が成功していますが、それは偶然弾丸と壁が重なるフレームがあったからに過ぎません。

Point:静的オブジェクト (Rigidbody 無し) に対する衝突判定のみで良い場合は Continuous を使う。

Continuous Dynamic モード

動くオブジェクト同士の衝突を検知したい場合は、Continuous Dynamic モードを使用します。先ほどの弾丸の Collision Detection を Continuous Dynamic に設定するとこのような挙動になります。

 

このように、2つのオブジェクトのどちらもが動いている場合は Continuous Dynamic モードを使うことができます。しかし、このモードには欠点があります。それは、オブジェクトの直線的な移動しか考慮されていないため、高速に回転するオブジェクトを貫通してしまうという点です。

次の動画では Continuous Dynamic に設定された弾丸を高速回転する棒で弾き返そうとしていますが...

 

回転による衝突が考慮されていないため棒を貫通してしまっています。

Continuous Speculative モード

この例のように、野球のバットや剣など、素早く回転する棒の衝突を正確に検知したい場合は Continuous Speculative モードを使用します。以下は弾丸の Collision Detection を Continuous Speculative に設定したものです。

 

このように Continuous Speculative ではオブジェクトの回転も考慮されるため意図通り弾丸を打ち返すことができています。
Continuous Speculative モードは、Unity 2018.3 で追加された新しいアルゴリズムで、Continuous Dynamic のほぼ上位互換といえるものです。Continuous Speculative の方が Continuous Dynamic よりも処理が軽く、精度が高いため、後述する「ゴースト衝突」がゲームの仕様上問題にならないのであれば Continuous Speculative を使用することをお勧めします。

Point:動くオブジェクト同士の衝突判定には原則 Continuous Speculative を使用する。

Continuous Speculative のゴースト衝突について

新しい衝突判定モードである Continuous Speculative ですが、これも万能というわけではありません。複数のコライダーが密接している場所の近くを通り過ぎると、見かけ上は衝突していないのに衝突したものとして誤検知されてしまうことがあります。

例としてこのようなオブジェクトを用意しました。

3つのキューブを FixedJoint で繋げたもので、コライダーも下図ように3つの Box Collider が密接している形になっています。

ファースト・パーソン・シューターなどで当たり判定を厳密に取りたい時があると思いますが、そのような用途において Continuous Dynamic と Continuous Speculative でどのような違いがあるのか比較してみましょう。

 

Continuous Dynamic

 

Continuous Speculative

 

いずれの動画も弾丸の Collision Detection モード以外はすべて同じ設定です。Continuous Dynamic ではターゲットのすれすれを弾丸がかすめていますが、Continuous Speculative では見かけ上弾丸に当たっていないのにターゲットが倒されてしまっています。このように、Continuous Speculative 使用時に近くの接触していないはずのコライダーに衝突判定が出てしまうことをゴースト衝突 (Ghost Collision) と言います。

ファースト・パーソン・シューターなどの競技性の高いゲームではこのような誤検知は大きな問題となってしまうでしょう。ですから、用途によっては軽量な Continuous Speculative よりも Continuous Dynamic を使用した方が良い場合もあるのです。

Point:ゴースト衝突がゲームの仕様上問題となる場合は Continuous Dynamic を使用する。

まとめ

これまでに説明した各 Collision Detection の仕様をまとめると、冒頭で紹介したフローチャートが完成します。

このチャートに沿って Collision Detection を選べば、必要な機能を持ち且つ負荷が最小限のモードを選ぶことができます。

皆様のゲーム開発に役立てていただければ幸いです。

 

参考ページ