エンティティを集約として作成する


10

私は最近、エンティティを動作から分離する方法と、この記事にリンクされている主な回答について尋ねました:http : //cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

ここで書かれている究極のコンセプトは、純粋な集合体としてのオブジェクトです。

C#を使用してゲームエンティティを純粋な集約として作成する方法を知りたいのですが。これがどのように機能するかという概念はまだよく理解していません。(おそらく、エンティティは特定のインターフェースまたは基本タイプを実装するオブジェクトの配列ですか?)

私の現在の考え方には、関連するインターフェイス(IMoveable、ICollectable、ISpeakableなど)を実装する各エンティティタイプの具象クラスがまだ含まれています。

エンティティの具体的なタイプを持たずに、純粋に集約としてエンティティを作成するにはどうすればよいですか?


それでも興味がある場合は、C#で小さなエンティティシステムをお送りします。それは驚くべきことではありませんが、動作します。
共産主義者アヒル

回答:


6

そのリンクされた記事でWestによって説明された「純粋な集約」アプローチは、「エンティティ」オブジェクトを完全に避けます。メモリ内に浮かんでいるコンポーネントがありますが、それらは暗黙の関係によってのみ結合されます。

これを行う1つの方法は、いわゆるアウトボードアプローチです。このようなシステムでは、コンポーネントはそれらを管理または制御するシステムによって保持されます(ここでは「管理」という用語を使用しますが、これは、保持する* Managerクラスの束があることを示唆しているという意味ではありません。コンポーネントタイプ)。たとえば、物理システムは、シミュレーションの世界で各剛体を表す多くのものを保持し、それらをPhysicsComponentsとして公開する場合があります。コンポーネントは、問題のサブシステムによって処理される実際のオブジェクトにすることも、必要に応じてそれらのオブジェクトのプロキシにすることもできます。

そのようなシステムでは、それを構成するコンポーネントへの参照のコレクションを保持する「エンティティ」クラスは必ずしも必要ではありません。代わりに、「エンティティ」の作成または破棄に関する通知が発生し、コンポーネントを処理する各サブシステムが、作成または破棄されたエンティティ(通常、一部のデータから読み込まれる)の説明を見て、コンポーネントがそのエンティティに必要かどうかを判断します。

このアプローチの利点の1つは、各コンポーネントの参照の局所性が非常に優れていることです。残念ながら、これは全体的に少し奇妙で、私が遭遇したコンポーネントベースのエンティティの中で最もフレンドリーな味ではありません。エンティティを表す実際のオブジェクトが他のサブシステムによってまだ保持されているコンポーネントへの弱い参照を集約するだけであっても、それが本当に便利な場合があります(他に何もない場合、コンポーネント間でメッセージをルーティングする簡単な方法を提供します) 。

コンポーネント指向のゲームオブジェクトシステムを実装するには、いくつかの良い方法があります。システムに必要な要件をしっかりと理解していれば、本当に役立ちます。Unityのような一般的なフレームワークが例として何をしているのかを見ることができます。厳密な要件を自分で設定しないと、実際にシステムを構築せずにシステムを際限なく「設計」し、完璧な実装にたどり着くという問題に遭遇する可能性があります。何らかの理由で、コンポーネントシステムでこれをよく見ました。


3

Unityが行う方法は、すべてのスクリプト(あなたのケースでは、ゲームオブジェクトのタイプに固有のゲームコード)MonoBehaviourが、より関連性の高いクラスから派生する基本クラスから派生するというものComponentです。GameObjectクラスを編集したり、コードにアクセスしたりすることはありません。

ゲームオブジェクトは、これらすべてのを格納する役割を果たしますComponent。表面上は、関連する関数の呼び出し(つまりUpdate)も担当しています。Unityはリフレクションを使用して呼び出す関数を決定します(このページの「オーバーライド可能な関数」セクションをご覧ください)が、おそらくそれらを仮想化したいと思うでしょう。

したがって、Unityで使用するメカニズムの1つは、現在のゲームオブジェクト(またはその子)のコンポーネントをタイプごとに取得することです。一般的なものをラップするヘルパープロパティがいくつかあります。たとえば、ゲームオブジェクトのTransformコンポーネントにアクセスする(ゲームオブジェクトの位置/回転/スケールを制御する)場合、通常はのようにする必要がありますがthis.GetComponent<Transform>().position、ヘルパーthis.transform.position呼び出しにラップします。別の一般的なパターンは、現在のゲームオブジェクトのRendererコンポーネントへのアクセスです。したがって、現在のゲームオブジェクトのマテリアルを変更するなどの操作を行う場合は、別のスクリプトからを実行するthis.renderer.material = someOtherMaterialと、ゲームオブジェクトが適切に更新されます。

Unityでこれが機能する方法の1つは、コンポーネントが既に接続されているシーンでゲームオブジェクトを作成できるようにエディターが設定されていることです。Unityの場合、すべてのゲームオブジェクトにはTransformコンポーネントがありますが、AudioListenerまたはのような組み込み型を含めることもできRenderer、期待どおりの動作をします。または、自分がやりたいことをすべて実行する独自のコンポーネントを追加できます。エディターはまた、コンポーネントのpublic / serializableフィールドを公開するため、同じ基本コードを使用したいが、いくつかのマジック番号を変更したい場合に、異なるスクリプトを作成する必要はありません。

全体として見た目はすばらしく、Unityの無料バージョンをダウンロードして、スクリプトシステムがどのように設定されているかを、達成したい概念のかなり適切な証明として試してみることをお勧めします。


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