Collision & spatial queries

Broad Phase / Narrow Phase

広域・詳細判定

候補抽出の後に精密な接触判定を行う。

10 / 10

Interactive demo

Preparing the demo…

Broad Phase / Narrow Phase

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

This explanation is currently available in Japanese.

ひとことで

衝突判定を、「ぶつかっていそうな組を大まかに絞る」広域判定(ブロードフェーズ)と、「残った組を正確に調べる」詳細判定(ナローフェーズ)の 2 段階に分ける考え方です。物体が NN 個あれば組は N(N−1)/2N(N-1)/2 通りあり、全部を正確に判定すると、物体の数の 2 乗に比例して時間がかかります。実際に接触しているのはほんの一部なので、まず AABB のような簡単な形で候補を絞り、重い判定は候補だけにかけます。ほぼすべての物理エンジンがこの構成です。

ゲームでの使いどころ

  • 物理エンジン:剛体どうしの接触を毎フレーム求める処理の、最初の段。
  • 弾と敵、プレイヤーとアイテム:数百〜数千の物体どうしの当たり判定。
  • トリガー・範囲の検出:範囲に入った物体のイベントを出す。
  • AI の近傍探し:近くの敵や味方を探す処理にも、同じ広域判定の構造を使い回せる。

しくみ

広域判定:物体を AABB で囲み、AABB が重なる組を効率よく探します。代表的な方法は 3 つです。

方法しくみ向いている場面
一様な格子・空間ハッシュセルに登録し、同じセルの物体どうしだけ比べる大きさのそろった多数の物体
スイープ・アンド・プルーン軸に投影した区間の重なりを、端点の並びで探す大きさがばらばら、動きが少ない
動的な BVH(AABB 木)箱の木をたどって重なる相手を探す大きさも動きもばらばら、レイキャストと共用

詳細判定:候補の組について、実際の形(球・カプセル・箱・凸多面体・メッシュ)どうしの正確な判定を行い、接触点・法線・めり込みの深さを求めます。形の組み合わせごとに専用の関数(球と球、球と箱など)を用意し、一般の凸形状には GJK や分離軸定理を使います。

広域判定がうまく働けば、全体の手間は「物体の数 + 候補の数」に比例し、2 乗の増え方を避けられます。

実装のポイント

  • 形の組み合わせの表:形の種類が kk 個なら、k×kk \times k の関数の表を用意して、組み合わせで呼び分けます。
  • フィルタを広域判定で:「味方の弾は味方に当たらない」のような衝突のレイヤー・マスクは、詳細判定の前に候補から外します。
  • 接触を使い回す:前のフレームで接触していた組は、次のフレームも接触していることが多いので、接触点や積み上げた力を使い回すと安定します(ウォームスタート)。
  • 静止した物体を眠らせる:止まっている物体どうしは判定を省き、動く物体との組だけを調べます。

つまずきやすい点

  • 広域判定の箱が大きすぎる:AABB が物体よりずっと大きいと、候補が増えて絞り込みの意味がなくなります。
  • 巨大な物体:床や地形のような巨大な物体は、ほかのすべてと候補になります。静的な地形は別の構造(BVH など)に入れ、動く物体からそこを問い合わせる形にします。
  • 組を 2 回数える:格子の複数のセルにまたがる物体は、同じ組が何度も候補に上がります。重複を取り除きます。

デモで試すこと

  1. 円と回転する箱が動き回っています。広域判定で残った候補の組が青い線で結ばれ、詳細判定で本当に接触していた物体が赤くなります。
  2. 左下で、「全部の組」と「詳細判定にかけた組」「接触していた組」を比べてください。広域判定があれば、候補の数は接触の数に近くなります。
  3. 「なし(全部の組を詳細判定)」に切り替えて、「物体の数」を増やすと、右下のグラフの判定時間が急に増えます。格子やスイープ・アンド・プルーンでは、ゆるやかにしか増えません。
  4. 「候補の組を線で表示」を切ると、判定の結果だけを見られます。

References

Box2D Collision ↗

A general reference for this subcategory.