2つのオブジェクトが相互作用する場合、相互作用コードは何を保持しますか?


28

弾丸と敵、またはプレイヤーと床を考えてください。これらのオブジェクトが相互作用する場合、相互作用コードを保持するものは何ですか?


2
どのような方法で対話しますか?衝突検出を意味しますか?その場合、衝突検出クラスと衝突解決マネージャーの両方を実装する可能性が最も高くなります。
キャプテンレッドマフ

部分的にはい、衝突と衝突後に何が起こるかに興味があります。弾丸は、敵の近くにあるかどうか、またはその逆を確認していますか?そして、衝突後に何が起こるのでしょうか?ご覧のとおり、全体がかなり混乱しているため、コードが非常に読みにくくなっています。
ThatOneGuy

回答:


23

TL; DR:

あなたのゲームオブジェクトはお互いを知りませんし、他のオブジェクトに対するチェックも実行しません。ゲームオブジェクトをチェックし、適切なアクションを実行してゲームの物理をシミュレートする衝突検出および衝突解決パターンを作成します。

良いもの

衝突検出を記述し、この本を読むという以前の試みから、衝突検出と衝突解決には2つの段階があります。最初の段階(衝突検出)は、2つのオブジェクトに潜在的な衝突があるかどうかを判断するアーリーアウトパスです。2つのオブジェクトが潜在的な衝突を形成する場合、これらのオブジェクトを2番目の段階(衝突解決)に渡し、オブジェクトに対してより詳細なチェックを実行し、衝突の解決を試みます。

エンジン/ゲームのどこかに、あなたの世界のすべてのオブジェクトの配列を保持します。各フレームで、配列をループし、単純なバウンディングボックス/球体衝突検出を使用して、他のすべてのオブジェクトに対して各オブジェクトをチェックします。

擬似コード:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

この種のループは非効率的ですが、空間的分割を使用して、衝突するには距離が離れすぎていることが保証されているオブジェクトのアーリーアウトとして、改善の余地があります。

2つのオブジェクトの潜在的な衝突をチェックした後(つまり、両方のオブジェクトが衝突するのに十分近い)、オブジェクトはより正確な衝突検出ルーチンを実行するために渡されます。

交差する可能性がありますが、ジオメトリに起因しないランダムな形状とサイズの2つのポリゴンがあるとします。

グーグル経由で見つかった画像

境界球を使用すると、これらの2つのオブジェクトは潜在的な衝突に対して偽陽性を作成します。ここで、2つのオブジェクトが実際に交差するかどうかを判断するために、より徹底的なパスを実行します。

真の衝突が見つかったら、衝突解決ステップで適切なアクションを実行し、ゲーム物理学の粒度とニーズに応じて力またはモーメントを適用することでオブジェクトを解決します。

これを念頭に置いて、衝突の検出と解決のプロセス全体を抽象化して、オブジェクトがお互いについて何も知る必要がなく、衝突を判断して解決するために必要なプロセスも不要にすることができます。これを処理する2つのクラス/マネージャーは、各オブジェクトの基本的なプロパティを知るだけで、衝突の迅速でダーティなチェックを実行し、必要に応じてより徹底的なチェックを実行できます。


2
特に、メディエーターの設計パターンが適切です。Observerパターンは、非常に異なる意図を持つ優れた代替案です。このStackoverflowの投稿でそれらのかなり良い要約を得ることができます
kurtzbot

12

Unreal Engine 3がそれを処理する1つの方法:

弾丸は、何かに当たったことを伝える引数とともに、何かに当たったという衝突メッセージを受け取ります。その後、objectHit.takeDamage(self)を呼び出すことができます。次に、ターゲットは、ヒットしたものへのポインターを含むTakeDamageメッセージを取得し、適切なアクションを実行します。

私はこのアプローチが個人的に好きです。というのは、弾丸は特別なアクションをとることができ(ヒットしたもののタイプに応じて何らかの爆発効果をもたらすなど)、ターゲットは弾丸のタイプに応じて特別なアクションをとることができるからです。

また、弾丸がターゲットに対して何を行うかを知っており、objectHit.freeze(self)のように、その弾丸に対して関数を呼び出すことができます。その後、ターゲットは、フリーズする何かにヒットしたこと、およびどのようなオブジェクトであったかを認識します。

編集:この答えは、おそらくUE3を使用していないため、どのように機能するかの一般的な図を意味します。:)


10

シーフは、ソースとレセプトロンを備えたダークエンジンでこれを非常にうまくやった。オブジェクトには、これらの両方のプロパティがあり、種類が異なります。たとえば、水の矢印には、接触時にWaterStimのソースがあります。爆発するとAoE FireStimが発生します。

Water Arrowがオブジェクトに当たると、ターゲットオブジェクトは、適切な強度値を持つWaterStimを探しているものをレセプトロンで検索します。次に、それに関連付けられているコマンドを実行します(この場合、燃えるトーチをオフトーチに変え、煙を一気に放出します)。

SystemShock2で同じエンジンが使用されているため、これがすべての異なるダメージタイプの処理方法であり、異なる弾丸は異なる刺激セットを持ち、異なるモンスターは異なる刺激タイプのレセプトロンを持ち、1 *、2 *、1 / 2弾薬の種類が「超効果的」かどうかに依存する強度。

レベルエディタでオブジェクトにソースとレセプトロンを追加できるため、非常に柔軟なシステムのように見えました(たとえば、火事に見舞われた場合に開くワンオフドアを作成するために)。オブジェクトに特別なスクリプトが関連付けられている場合。

したくないことは、考えられるすべてのオブジェクトと衝突する可能性のあるすべてのオブジェクトのnXn相互作用行列をハードコーディングする必要があることです!標準化されたメッセージを通じて相互作用を一般化することにより、プロセスを簡素化します。


スクリプトの観点から、このアプローチは最も柔軟で最も表現力があります。とてもかっこいい。
-drhayes

-2

1つの解決策は、弾丸とプレイヤーのコンテナを別々のクラスに保持し、その後、フレームループが相互作用の責任を負うmain()関数を保持することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.