正しい答えは、設計している実際のゲームによって少し異なります。どちらかを選択するには、実際に両方を実装し、特定のゲームでどちらがより時間的または空間的に効率的かを調べるプロファイリングを行う必要があります。
グリッド検出は、移動するオブジェクトと静的な背景の間の衝突の検出にのみ適用されるようです。これの最大の利点は、静的な背景が連続したメモリ配列として表されることであり、複数の読み取りを行う必要がある場合、各衝突ルックアップは良好な局所性を持つO(1)です(エンティティがグリッド内の複数のセルをカバーするため)。静的な背景が大きい場合の欠点は、グリッドのスペースがかなり無駄になる可能性があることです。
代わりに、静的な背景をクワッドツリーとして表す場合、個々のルックアップのコストは高くなりますが、背景の大きなブロックが少量のスペースを占有するため、メモリ要件が低下し、より多くの背景がキャッシュ。そのような構造でルックアップを行うのに10倍の読み取りが必要な場合でも、すべてがキャッシュ内にある場合、キャッシュミスのある単一のルックアップよりも10倍高速です。
私が選択に直面した場合は?私はグリッドの実装を採用します。なぜならば、それは簡単で、他のより興味深い問題に時間を費やすのが簡単だからです。ゲームの実行が少し遅いことに気付いたら、プロファイリングを行い、何が役立つかを確認します。ゲームが衝突検出に多くの時間を費やしているように見える場合は、クワッドツリーなどの別の実装を試し(最初に簡単な修正をすべて試した後)、それが助けになるかどうかを調べます。
編集:グリッドの衝突検出が複数のモバイルエンティティの衝突の検出にどのように関連するかについての手掛かりはありませんが、代わりに、空間インデックス(Quadtree)が反復ソリューションよりも検出パフォーマンスを改善する方法についてお答えします。素朴な(そして通常は完璧な)ソリューションは、次のようなものです。
foreach actor in actorList:
foreach target in actorList:
if (actor != target) and actor.boundingbox intersects target.boundingbox:
actor.doCollision(target)
これは明らかにO(n ^ 2)付近のパフォーマンスを持ち、nは弾丸や宇宙船、エイリアンを含め、ゲームで現在生きている俳優の数です。また、小さな静的障害物を含めることもできます。
これは、そのようなアイテムの数が適度に少ない限り、素晴らしくうまく機能しますが、チェックするオブジェクトが数百を超えると少し貧弱に見え始めます。10個のオブジェクトの場合、衝突チェックは100個のみ、100個の場合は10,000個のチェックになります。1000は100万のチェックになります。
空間インデックス(クアッドツリーなど)は、幾何学的関係に従って収集するアイテムを効率的に列挙できます。これにより、衝突アルゴリズムが次のように変更されます。
foreach actor in actorList:
foreach target in actorIndex.neighbors(actor.boundingbox):
if (actor != target) and actor.boundingbox intersects target.boundingbox:
actor.doCollision(target)
これの効率(エンティティの均一な分布を想定):通常O(n ^ 1.5 log(n))です。インデックスはトラバースするためにlog(n)の比較を必要とするため、約sqrt(n)の近隣が比較されます、確認するアクターはn人です。ただし、実際には、衝突が発生した場合、ほとんどの場合、オブジェクトの1つが削除されるか、衝突から遠ざかるので、近隣の数は常にかなり制限されます。したがって、O(n log(n))だけが得られます。10個のエンティティの場合、(約)10個の比較を行います。100個の場合は200個、1000個の場合は3000個です。
本当に巧妙なインデックスは、近隣検索と一括反復を組み合わせて、交差する各エンティティでコールバックを実行することさえできます。インデックスはn回クエリされるのではなく、1回スキャンされるため、これによりO(n)程度のパフォーマンスが得られます。