Collision & spatial queries

Continuous Collision Detection / Shape Cast

連続衝突判定

移動途中も調べて高速物体のすり抜けを防ぐ。

2 / 10

Interactive demo

Preparing the demo…

Continuous Collision Detection / Shape Cast

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

物体が 1 フレームの間に動く通り道全体を調べて、途中で何かに触れる瞬間を求める衝突判定です。ふつうの(離散的な)判定は、各フレームの位置だけを見るので、速い物体が薄い壁を 1 フレームで飛び越えると、壁の手前と向こう側にしかいない瞬間になり、衝突を見逃します(トンネリング、すり抜け)。連続衝突判定(CCD)は、前の位置から次の位置までを太さのある線分として掃引し、最初に接触する時刻(TOI)を求めるので、どんなに速くても当たります。

ゲームでの使いどころ

  • 弾・矢・投げた物:速い弾が敵や壁をすり抜けないようにする。
  • プレイヤーの高速移動:ダッシュや落下の速度が大きくなっても、床や壁を抜けない。
  • 物理エンジンの設定:Unity の Collision Detection(Continuous)、PhysX や Box2D の「bullet」フラグなど、速い物体だけに CCD を有効にする。
  • 形状キャスト:「この位置からこの向きへ球を動かしたら、どこで何に当たるか」を調べる(スフィアキャスト、ボックスキャスト)。キャラクターの移動や、壁ぎわの押し戻しに使う。

しくみ

すり抜けが起きる条件:1 フレームに進む距離 v Δtv\,\Delta t が、壁の厚さと物体の大きさの合計より大きいと、重なる瞬間がないまま通り過ぎることがあります。

v Δt>w+2rv\,\Delta t > w + 2r

(ww は壁の厚さ、rr は物体の半径)。速さ 120 m/s の弾を 60 Hz で更新すると、1 フレームに 2 m 進むので、厚さ 10 cm の壁は簡単にすり抜けます。

対策 1:サブステップ:1 フレームを細かく刻み、刻みごとに判定します。確実ですが、刻むほど判定の回数が増えます。

対策 2:掃引(形状キャスト):物体を、前の位置 p0\mathbf{p}_0 から次の位置 p1\mathbf{p}_1 へ動く線分として扱い、相手を物体の半径だけ太らせた形(ミンコフスキー和)と線分の交差を調べます。球と平面・球と箱などは、レイキャストと同じ式で最初に触れる割合 t∈[0,1]t \in [0, 1] が求まります。

対策 3:保守的な前進:一般の凸形状どうしでは、GJK で今の距離 dd を求め、「近づく速さの上限」vmax⁡v_{\max} で割った時間 d/vmax⁡d / v_{\max} だけは確実にぶつからないので、その分だけ進めることをくり返して接触時刻に近づきます。

実装のポイント

  • 速い物体だけに使う:CCD は通常の判定より重いので、速さが一定以上の物体や、弾・プレイヤーなど大事な物体だけに使います。
  • 残りの時間:接触した時刻 tt で止めたあと、反射させた向きに残りの時間 (1−t)Δt(1 - t)\Delta t だけ進めると、エネルギーを失わずに跳ね返ります。
  • 回転:回転しながら動く細長い物体は、位置だけの掃引では端がすり抜けます。回転も考える CCD(保守的な前進)が必要です。
  • 固定の時間刻みと組み合わせる:描画のフレームレートが落ちて Δt\Delta t が大きくなると、すり抜けが起きやすくなります。物理は固定の刻みで更新します。

つまずきやすい点

  • 薄い壁を作らない:CCD がなくても、壁に十分な厚みを持たせるだけで、多くのすり抜けは防げます。レベル作りの段階で気をつけます。
  • 動く物体どうし:両方が速く動く場合、片方だけを掃引しても見逃します。相対的な動きで調べます。
  • 接触の時刻で止めすぎる:毎回ぴったり接触時刻で止めると、斜めに壁へ当たったときに滑らずに止まってしまいます。残りの時間で壁に沿って滑らせます。

デモで試すこと

  1. 3 本の通路に、同じ速さの弾を同じ時間刻みで撃ち、スローモーションで見せています。青い点は、物理の更新ごとの弾の位置です。
  2. 「離散」では、点が壁の手前と向こう側にしかなく、弾がすり抜けて緑になることがあります。「すり抜け」の回数を比べてください。
  3. 「サブステップ」は細かく刻んで必ず当てますが、判定の回数がずっと多くなります。「連続」は、通り道(黄色)と壁の交差から、1 回の判定で当たる位置を求めます。
  4. 「弾の速さ」を下げるか「物理の更新」を増やして、1 ステップに進む距離が壁の厚さより小さくなると、離散でも当たるようになります。

References

Box2D Collision ↗

A general reference for this subcategory.