衝突検出アルゴリズム
衝突検出
- ビデオゲームプログラミングでは、衝突検出は非常によくある問題
- キャラクター同士がすり抜けないようにしたり、物理エンジンを実装したりするうえで不可欠
単純なアプローチ 🐥
パフォーマンスの問題
- オブジェクト数が増えるほどパフォーマンス上の問題が発生する
- たとえば n = 20 のとき、190 組を検査する必要がある
解決策の改善
ソートによる最適化
- オブジェクトを x 座標に従ってソートすると、不要な検査を減らせる
- コード例:
sortByLeft(balls);
for (let i = 0; i < balls.length; i++) {
const ball1 = balls[i];
for (let j = i + 1; j < balls.length; j++) {
const ball2 = balls[j];
if (ball2.left > ball1.right) break;
if (intersects(ball1, ball2)) {
bounce(ball1, ball2);
}
}
}
パフォーマンス分析
- ソート: O(n log n)
- 内側のループ: 平均して O(n + m)(m は x 軸上で重なっている総数)
- 最終的な時間計算量: O(n log n + m)
視覚的な比較
- 全ペア検査と、ソート済みペア検査の比較
- ソート済みペア検査のほうが、はるかに少ない検査で済む
GN⁺のまとめ
- この記事は、ゲーム開発における衝突検出アルゴリズムを最適化する方法を扱っている
- 単純な O(n^2) アルゴリズムから始めて、ソートによって性能を大きく向上させる
- ゲーム開発者やソフトウェアエンジニアにとって非常に有用な情報
- 類似機能を持つ他のプロジェクトとしては、Box2D、Bullet Physics などがある
1件のコメント
Hacker Newsのコメント
著者は最適なパフォーマンスのために、mergesort や quicksort のような「高速」なソートアルゴリズムを使うことを提案している
過去に似たような作業をしたことがあるが、ソートの代わりに各方向ごとのインデックスリストを維持していた
objectIndicesSortedByLeftEdge/RightEdge/TopEdge/BottomEdgeのような 4 つのリストがあるこの記事は本当によく整理されている
連続衝突検知に関する文書はいつも楽しく読んでいる
イラストの使い方が良かった
Part 2: https://leanrada.com/notes/sweep-and-prune-2/
「この単純なアルゴリズムは Big O の用語では O(n^2) 時間で実行される」という主張に疑問を呈している
この方法が、潜在的な衝突候補を減らすためにクワッドツリーを使うのと似ているのか気になった
線形計画法が提案されたことがあるのか気になった
このウェブサイトには良い意味で気を取られた