エンティティコンポーネントシステム-オブジェクトの変換を実装する方法


11

エンジンのエンティティコンポーネントシステムを設計する際に、特定のタイプのコンポーネントを格納および取得する方法に少し問題がありました。

最初に、この質問で使用する少しの用語を明確にします。

  • コンポーネント」を、特定のシステムに関連するデータを格納するデータ構造と呼びます。
  • 私は、「システム」をメソッドとデータ構造の集合体と呼び、コンポーネントを使用してユーザーとのゲームの状態/インターフェースを更新します。
  • エンティティ」は基本的に、特定のコンポーネントを取得し、ゲームロジックでそれらのデータを変更するために使用される単なるIDです。

各システムは、コンポーネントのタイプ(例:Physics-> PhysicsComponent、AI-> AIComponent、Rendering-> RenderingComponent)の(IDマップ)配列を所有しているため、データを効率的に反復できます。

ただし、すべてのコンポーネントが特定のシステムによって所有されているわけではありません。たとえば、Transformコンポーネントはオブジェクトの位置、回転、スケールを保存します。物理学、AI、レンダリングなどの多くのシステムで使用されているため、エンティティの最も重要な部分の1つです(Unityは必須にします)。

これはほとんど私が直面している問題です。Transformは他の多くのシステムで使用されているので、コンポーネントごとに使用するものを取得するにはどうすればよいですか?考えられる解決策の1つは、各コンポーネントに独自のエンティティIDを格納させることです。このようなコンポーネントを取得するのは簡単ですが、それほど効率的ではありません。また、他のコンポーネントを認識していない、分離された独立したデータのバンドルとしてのコンポーネントの概念に反します。

この問題を解決する適切な方法はありますか?Transformもコンポーネントにする必要がありますか?


3
以下のための+1 :「最初は、私はこの質問に使用するつもりだ用語のビットをクリアしてみましょう」
Vaillancourt

このタイプの質問をこのサイトでもっと見たいです。+1
S.TarıkÇetin2017

すべてのコンポーネントをグローバル変数として格納するだけ
Miles Rout

回答:


2

これはかなり広い質問であり、その答えはあなたのアーキテクチャに強く依存します。ただし、一般的な回答をさせていただきます。

物理システムとレンダリングシステムには変換が必要ですが、AIシステムには必要ありません。したがって、独自のコンポーネントクラスに変換をカプセル化することは理にかなっています。このような関心のあるシステムはすべて同じデータを使用するため、エンティティが変換オブジェクトへのポインタ、または別の場所に格納されている変換オブジェクトのIDを持つことは理にかなっています。

後者のソリューションを選択した場合、変換に関係する各システムは、変換オブジェクトが格納されている場所にアクセスする必要があります。

前者を選択した場合、各システムが実行する必要があるのは、エンティティ自体にアクセスし、変換を要求することだけです。

前者の場合、問題は、OOPルールに違反することなく、各システムへの変換用のストレージへのアクセスを許可する方法になります。

後者の場合はそのような問題はありませんが、コンポーネントオブジェクトのIDではなくオブジェクトへのポインタを格納するようにエンティティオブジェクトのデザインを変更する必要があります。

私の個人的な好みは、コンポーネントクラスへのポインタを格納するようにエンティティークラスを設計することです。これにより、多くの設計上の問題が簡素化されます。このようにして、変換を必要とする各システムはエンティティにそれを要求し、要求しない場合はそれを無視できます。ただし、これにはポインターに固有の計算オーバーヘッドが伴います。これはキャッシュミスのコストです。

詳細については、このECSの概要をご覧ください。

結局のところ、どちらがより重要であるか(開発の容易さ、またはパフォーマンス)を決定するのは、あなた次第です。

最後に、あなたの質問は、ECSの支持者が考えるデザインの質問の優れた例であり、明確な特効薬のソリューションはないことを指摘しておきます。


あなたの提案をありがとう。ただし、質問があります。なぜAIシステムはオブジェクトの位置を必要としないのですか?
CRefice 2017

位置(3つのフロートのベクトル)と平行移動(位置ベクトルから構築された変換行列)を混同しています。変換マトリックスは、変換、回転、スケール変換から構成されます。これはAIシステムが必要とする情報よりはるかに多くの情報ですが、そこから位置ベクトルを抽出することもできます。個人的には、位置、方向、サイズを独自のコンポーネントに分離し、それらを使用して変換を作成および更新します。
Ian Young

@IanYoungそれらを分離することは、位置と方向を個別に行うよりも頻繁に位置と方向を一緒に必要とする場合に、潜在的に良いよりも害を及ぼす可能性があります。その場合、位置と方向のデータ属性を単一のコンポーネントに配置すると、キャッシュのパフォーマンスが向上します。
Naros

1
私の好みは、位置、方向、およびスケールの3つすべてを1つのコンポーネントに結合することであり、特定のサブシステムが位置または方向のみを必要とする場合は、データを複製し、ゲームループの明確に定義されたポイントでそれらを同期することを推奨します。
Naros

@Narosはい、これは私が意味したものです。2つのコンポーネント、Transform、および(私のフレームワークでは)SpatialData。これには、位置、速度、向き、角速度が含まれます。位置と方向は、トランスフォームの作成と更新に使用されます。
Ian Young
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.