コンポーネントベースのゲームで衝突を適切に処理する方法は?


11

コンポーネントを中心に設計されたゲームで衝突を適切に処理する方法に頭を悩ませようとしています。

多くの例ではPhysicsComponent、エンティティのコンポーネントのリストに何らかの種類の追加が加えられていますが、実際の実装では混乱します。

これPhysicsComponentが機能するためには、周囲の世界にアクセスする必要があります。これは私には直感的な意味がありません。コンポーネントは、そのコンテナ(エンティティ)だけでなく、そのコンテナのコンテナ(世界)を認識すべきではありませんか?

私には、レベルまたはシーンがこれらのエンティティのリストを維持し、ゲームが更新されるたびに、エンティティをループしてどのコリジョンを決定するように聞こえます。

私の質問は、第一に、これが良い設計であるかどうか、そして第二に、どのエンティティが衝突できるかを決定する方法です。ソリッドエンティティは空のIRigidBodyインターフェイスを実装できるので、レベルはリスト内のどのエンティティが衝突をサポートするかを決定できます。しかし、これはコンポーネントの設計を壊していますか?

代わりに、空のRigidBodyコンポーネントを含める必要がありますか?常に空であるとは限らず、このアプローチはより将来性があるため、これは実際により良い場合があります。これに関する唯一の問題は複雑さです。シーンは、すべてのエンティティだけでなく、すべてのエンティティのコンポーネントもループして、このRigidBodyコンポーネントがあるかどうかを判断する必要があります。

第三に、それらが衝突した場合、両方のエンティティに何らかの方法で通知する必要があり、これを達成する方法については確信がありません。

両方のエンティティにHealthComponentが含まれていて、衝突すると両方のヘルスが任意の値5減少するとします。2つのエンティティ間の衝突を検出した場合、これを処理するのはシーンの責任です。

しかし、その後、シーンはあまりにも責任がありますか?エンティティがアクセスしてはならない(?)ものの多くをシーンが担当している場合、これが手に負えなくなり、扱いにくくなるのを見ることができました。

編集:詳細が更新された質問。



Andrewのリンクされた回答、Jamesの回答、およびNick Wiggillの回答はすべて+1に値します。コンポーネントは、データとメソッドの両方を持つ典型的なクラスというよりもデータと考えてください(メソッドを持たないというわけではありませんが、多くの責任を与えられるべきではありません)。優れたコンポーネントフレームワークの例については、Artemisコンポーネントシステム(piemaster.net/2011/07/entity-component-artemis)をご覧ください。
michael.bartnett

回答:


5

正直なところ、コンポーネントの設計面から見ると、私のコンポーネントは、必要な場合を除いて互いを知りません(それは非常にまれです)。それでも、私は通常、コンポーネントがコンポーネントではなく、コンポーネントの管理システムと直接対話することを好みます。(スクリプティングインターフェイスはオブジェクトからオブジェクトへのように見えますが、実際のエンジンではそうではありません)。

そのために、私はあなたが最初に言ったことに賛同し、オブジェクトの衝突をテストする必要がある場所に存在する物理コンポーネントを使用します。明らかにこれらのオブジェクトは衝突解決時に他のコンポーネントに通知する必要があるかもしれませんが、前述のように、ここでは別のインターフェイス(マネージャーまたはイベントメッセージングシステムのいずれかを介して)たとえば、それらの1つがあります)。

私はあなたが正しい軌道に乗っており、「はい、それは正しい音」をもっと必要としていると思います。

お役に立てれば!


3

通常、ゲームエンジンはサードパーティライブラリを使用して、エンティティ間の衝突を検出します。そのシナリオでは、PhysicsComponentを持つエンティティを「物理」世界に作成または登録します。そして、2つのエンティティ(AとB)間の衝突を検出するたびに、通常はエンティティAにコールバックを呼び出し、エンティティBに衝突したことを通知し、エンティティBに同じことを通知し、エンティティAに衝突したことを通知します。

2Dの場合、よく知られている無料の物理ライブラリはBox2Dです。また、シマリスを見てみる価値があります。3Dの場合、Bulletは無料です(おそらく、あなたが見つけることができる最高の無料のものです)。HavokとPhysXは、トリプルAゲームの多くで使用されていることで有名です。


2

あなたが持っている問題は、衝突検出(1つの物理成分を保持するエンティティが別のものを参照する必要がある唯一の理由です)が、通常はゲームループによって、またはこれを行うヘルパー関数/クラス。数週間前の誰かに対する私の答えは、同様の理由でのエンティティの削除について語っていますが、衝突がエンティティの1つを破壊する場合、その同じ答えは、そのコンテキストで、あなたに非常に関連していることに注意してください、「より高い力」はまだ体の浄化を管理しなければならないので...いわば。

エンティティ間でこれを行うだけでは、一般的に実行できません。ソリッドアーキテクチャでは、衝突検出などの直接管理を介するか、たとえば クライアントサイドメッセージングマネージャーがプレーヤーからディスパッチされたメッセージをリッスンし、サーバーに送信して全員に再ブロードキャストするプレーヤーメッセージングシステム。


2

私は今、プロジェクトであなたとまったく同じ問題に直面しています。私がそれに取り組むことを決めたのは、物理エンジンのボディを保持する「ColliderComponent」を持つことです。ボディは外部で定義され(実行時にロードされるシェイプ定義)、物理ワールドそれらが属するゲームエンティティに追加されます。

Box2Dを使用しています。ここでは、衝突によって通知される「衝突リスナー」を添付できます。ボディのユーザーデータに「ColliderComponent」へのポインターを追加するため、衝突の一部である2つのColliderComponentsを取得できます。

したがって、衝突が発生したときに発生することは次のとおりです。衝突の一部であったColliderComponentsは所有者オブジェクト(ゲームエンティティ)にメッセージを送信し、所有者オブジェクト(ゲームエンティティ)はそのメッセージをすべてのコンポーネントにブロードキャストします。

その後、すべてのコンポーネントがそのメッセージに反応できるため、「ヘルスコンポーネント」はヘルスなどから5ポイントを削除できます。


+1:非常によく似たアプローチを使用しています。衝突したエンティティのタイプに応じて、発生する損害の量をどのように判断しますか?
デン

@Den発生した衝突に応じて、異なるメッセージ(またはメッセージデータ)を送信します。処理する多くの異なるケースがないので、これはうまく機能します。
bummzack

0

衝突の「世界」を認識する衝突システムを作成します。次に、コリジョンコンポーネントで、コリジョンシステムにポイントAからBにレイをキャストし、衝突したかどうかを応答するように指示します。

幸運を。衝突システムは、ゲームエンジンの退屈な部分の1つであることがわかりました。

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