エンティティコンポーネントシステムでのエンティティの「タイプ」の識別


10

エンティティに明示的な「タイプ」(例:プレーヤー)がなく、単にコンポーネントのコレクションである場合、システムで作業する必要があるエンティティとそうでないエンティティを識別するにはどうすればよいですか?たとえば、ポンのゲームでは、パドルとボールの両方がウィンドウの境界に衝突します。ただし、それぞれの衝突処理システムは異なるため、システムは間違ったタイプのエンティティを処理するべきではありません。

void PlayerCollisionSystem::update(std::vector<Entity *> entities) {
  typedef std::vector<Entity *>::iterator EIter;
  for (EIter i = entities.begin(); i != entities.end(); ++i) {
    Entity *player = *i; // How do I verify that the entity is a player?

    // Get relevant components.
    PositionComponent *position = player->getComponent<PositionComponent>();
    VelocityComponent *velocity = player->getComponent<VelocityComponent>();
    SpriteComponent *sprite = player->getComponent<SpriteComponent>();

    // Detect and handle player collisions using the components.
  }
}

プレーヤーとボールの両方が衝突処理に関連する同じコンポーネントタイプを共有していますが、システムの実装は異なります。

すべてのゲームエンティティのコンテナがある場合、Entityなどのメンバー変数を継承または含めずに特定のタイプのエンティティを識別するにはどうすればよいですか。std::string typeこの場合、エンティティは単なるコンポーネントのコレクションではなくなりますか?

回答:


21

Nicol Bolasの答えはまっすぐですが、脇に寄って問題を遠くから見てみます。エンティティの種類は本当に必要ありません。

「オブジェクトにコンポーネントがあるか」を気にする必要があるだけXで、問題は適切に識別されていないことですX。2つのオブジェクトの動作が異なる場合は、それらに異なるコンポーネントを指定するか、コンポーネントにブールフラグを設定して、異なるオブジェクト構成に対して異なる動作をさせるようにします。エンティティの「タイプ」ではなく、コンポーネントシステムを使用して動作に関する決定を行います。これがコンポーネントを使用する全体のポイントです。

動作が異なる場合は、PaddlePhysicsコンポーネント/システムと個別のBallPhysicsコンポーネント/システムを使用することが完全に許可されています。または、コンポーネントをより細かい部分に分割してBounce、Ballのみが持つStopAtBoundaryコンポーネントと、両方がBallありPaddle、動作の一部がコードの共有を正当化するほど複雑な場合に持つコンポーネントを用意することもできます。それとも、ただ作ることができるPongPhysicsブールフラグ持つコンポーネントBouncesセットtrueのためにBallfalseのためにPaddle。基本WallCollisionコンポーネントを作成し、そのコンポーネントを派生させてBallWallCollision、そこに必要な追加の動作を追加するを取得することもできます。


4
「バニラ」ECSには制約や問題がないので、これは受け入れられる答えであると思います。エンティティのタグ付けは、マーカーとして機能する専用コンポーネントを作成することで簡単に実行できます。また、タグとして機能するだけで、何も実行しないダミーのPlayerTypeComponentでもかまいません。
tiguchi 14

19

システムは、それが役立つ場合にのみ役立ちます。エンティティが「単にコンポーネントのコレクション」であるシステムが、エンティティがほとんど「コンポーネントのコレクション」であるシステムよりも有用性が低い場合は、そのようにします。

「純粋な」システムを作ることをやめ、必要なことを実行する優れたシステムを作ることに集中してください。コンポーネントが役に立たなくなるまでコンポーネントを使用します。次に、別のものを使用します。

あなたはすでに、これに値する以上の時間を費やしてきた。


とても良い+1「あなたはすでに、これに値する以上に多くの時間を費やしてきました」
wes

8
これは正解ではないと思います。ECSの改善のトピックは大きな注目に値するものであり、ガリー(2013年に投稿したとき)はおそらくそれについて十分な時間を費やしていませんでした。トピックがこれ以上の時間に値しないという概念は、システムが単純または平凡であり、一般的に私たちの時間に値しないものであるべきであることを意味します。私はショーン・ミドルディッチの答えを好むと思います。なぜなら、それは実際に質問を却下するのではなく答えようとするからです。
Gavin Williams

すばらしい答えです。私は時々自分自身にこれを言わなければならないことに気づきます。前進することに焦点を当てます。
ドミニクBou-Samra

5

エンティティに明示的な型を指定する場合、最も簡単な方法は、エンティティクラスで型変数を定義することです。ECのパターンは、それが役立つ限り維持してください。

それ以外の場合、タイプはコンポーネント属性を介して暗黙指定されます。たとえば、物理コンポーネントには、モバイルと静止の属性があります。システムは、2つの携帯電話が衝突するタイミング(ボールとパドル)を認識します。同様に、衝突システムがどのように応答するかについての属性を持つことができます。オブジェクトを停止するか、それを反映しますか?属性を見ると、エンティティが何であるかがわかるはずですが、無関係なはずです。システムは、処理対象のエンティティタイプが何であるかを知る必要はありません。システムに提供されるコンポーネントを使用して、十分な情報を提供する必要があります。

最後に、タイプを含む追加コンポーネントを追加できますが、エンティティにタイプを追加する場合と同様に、多くのタイプ固有のコードを記述して、ECシステムの目的を無効にすることになります。


0

エンティティはコンポーネントのセットです。ランダムセットにきちんとしたラベルを割り当てることはできません。タイプの制約をあきらめることは、大きな柔軟性の代償です。

もちろん、コンポーネントに制限を課す特別な(型付きの)エンティティークラスを持つことができます。

理想的には、コンポーネントは独立しています。したがって、問題の解決策は、各サブコンポーネントの衝突処理を順番に呼び出すことです。実際のアプリケーションでは、相互依存性と順序付けの問題があります。その場合は、Entityクラスのすべてのメソッドに「ディスパッチャー」ロジックが必要です。

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