日曜大工のソリューションをお探しの場合は、次のことをお勧めします。
地形
できれば、地形をグリッドにして、各頂点の高さを変えてください。結果は、それぞれが(x、y)平面で同じ寸法を持つ一連の四角形になります。頂点には、勾配を構成するためにさまざまな(z)値があります。グリッド配置により、衝突チェックを実行するときに交差をテストする必要がある三角形を簡単に決定できます。
それがオプションでない場合(モデリングパッケージに事前に構築された地形)、とにかくメモリ内グリッドを使用し、各セル内に(部分的に)ある三角形のリストを保存することをお勧めします。
衝突をチェックしています
最も簡単なアプローチは、アクターが空間内のポイントを指すことを検討することです。次に、その時点での地形の高さを次のように決定します。
- ポイントが入っているグリッドセルを決定する
- セルに関連付けられた三角形を取得する
- ((x、y)平面内の)点を含む三角形を取得します
- ポイントでの三角形/平面の高さを取得します
「純粋なグリッド」地形の場合、ステップ3では、2つの三角形のどちらが必要かを判断するために、単一のポイント/平面チェックを行います。それ以外の場合は、三角形ごとにポイントイントライアングルチェックを実行する必要があります(ポイント/プレーンチェックを再利用するか、BSPを使用してさらに最適化することができます)。
ステップ4擬似コード:
point = [ x, y, z ] // actor position
relativePt = point - triangle.vertices[0]
normal = triangle.plane.normal
distance = relativePt DOT normal // (this is a dot-product)
intersection = [
point.x,
point.y,
point.z + distance / normal.z ]
これにより、アクターの位置から真っ直ぐ上下する光線と三角形の平面との交点が計算されます。これが、その(x、y)位置での地形の高さです。次に、アクターの位置がその高さより下にあるかどうかを簡単に確認し、下にある場合は、そのz座標を地形の高さに設定します。
オブジェクト(家、木、...)
各オブジェクトに、実際の形状にほぼ対応する1つ以上の凸状の衝突ボリュームを指定します(Unreal Engineがオブジェクトの衝突船体とどのように連携するかについては、UDNのこのページを参照してください)。
アクターを移動するときに衝突をチェックするすべてのワールドオブジェクトのどれをすばやく決定するには、いくつかの空間細分割手法を使用する必要があります。ほとんどの動きが2次元である場合(たとえば、地形と一部の家)、単純なグリッドまたは四分木(さらに細分化されたグリッドのようなもの)を使用できます。3次元オプションは八分木です。
空間細分割のポイントは、グリッドとして編成された地形の場合と同じです。配置オブジェクトを空間内のセル/ボリュームに関連付けて、すべてのオブジェクトとの衝突をチェックするのではなく、衝突をチェックするオブジェクトのセットを決定できるようにします。 。
衝突をチェックしています
- 使用した空間細分割手法を使用して、「潜在的な衝突オブジェクト」を取得します。feは、アクターの現在のグリッドセル内のオブジェクトを取得します。
- 各オブジェクトの凸状衝突ボリュームごとに:
- 分離軸定理を使用して、アクターが衝突ボリュームと交差するかどうかを判断します。いくつかの実装のヒントについては、別の投稿に対する私の回答を参照してください(その質問は、2Dの場合に関するものですが、コードは主に適用されます。「エッジ」を「平面」と読みます)。
- 衝突が発生した場合は、「問題のある平面」の1つの法線を使用して、アクターをその平面のすぐ隣に移動します。
注:この場合、アクターの衝突ボリュームをボックスまたは3面シリンダーなどとしてモデル化します。
また、オブジェクトごとにBSPツリーを構築し、代わりにアクターに軸に沿ったバウンディングボックスを使用することを検討することもできます。しかし、それはこの答えの範囲を少し超えています。オブジェクトの衝突ボリュームがより複雑になる場合は、より高速になります。
最終的な考え
まあ、これはすでに本当に長い答えです、そしてこれらはほんのいくつかの広いストロークです。衝突はかなり幅広いトピックです。ニーズに応じてさまざまなアプローチをとることができるからです。
たとえば、アクターが移動したときに衝突を検出する「トレース衝突」については説明していません。代わりに、オブジェクトに関する上記の提案は、アクターがオブジェクト内にあるかどうかをチェックします。これはあなたのニーズに合うかもしれないし、合わないかもしれません。
また、アクターとアクターの衝突については説明していないことに気づきました。おそらくそれは、(x、y)平面で2つの円を衝突させ、それらの垂直方向のスペースが交差するかどうかを確認するための追加のチェックとして行うのが最適です。
とにかく、私は本当にこれをまとめなければなりません。うまくいけば、これは少なくともあなたを正しい方向に向けるでしょう。