少しの経験から、厳密なOO設計からエンティティコンポーネントシステム(ECS)設計に移ります。
昔、私はあなたのようでしたが、似たようなプロパティを持つさまざまな種類のものがたくさんあり、さまざまなオブジェクトを構築して、それを解決するために継承を使用しようとしました。非常に賢い人は、それをしないで、代わりにEntity-Component-Systemを使用すると私に言った。
現在、ECSは大きな概念であり、正しく理解するのは困難です。エンティティ、コンポーネント、システムを適切に構築するために、多くの作業が行われます。ただし、その前に、用語を定義する必要があります。
- エンティティ:これはある事、プレーヤー、動物、NPC、何でも。それはそれに接続されたコンポーネントを必要とするものです。
- コンポーネント:これは、「名前」、「年齢」、「親」などの属性またはプロパティです。
- システム:これは、コンポーネントの背後にあるロジック、または動作です。通常、コンポーネントごとに1つのシステムを構築しますが、それが常に可能であるとは限りません。さらに、システムは他のシステムに影響を与える必要がある場合があります。
だから、これは私がこれで行くところです:
何よりもまず、ID
キャラクターのを作成します。アンint
、Guid
あなたが好き。これが「エンティティ」です。
次に、あなたが行っているさまざまな行動について考え始めます。「家系図」のようなもの-それはふるまいです。それをエンティティの属性としてモデル化する代わりに、そのすべての情報を保持するシステムを構築します。その後、システムはそれをどう処理するかを決定できます。
同様に、「キャラクターは生きているのか死んでいるのか」というシステムを構築したいと考えています。これは、他のすべてのシステムに影響を与えるため、設計で最も重要なシステムの1つです。一部のシステムは「死んだ」文字(「スプライト」システムなど)を削除できますが、他のシステムは新しいステータスをより適切にサポートするために内部で再配置できます。
たとえば、「スプライト」、「描画」、または「レンダリング」システムを構築します。このシステムは、キャラクターをどのスプライトとともに表示する必要があるか、およびどのように表示するかを決定する責任があります。次に、キャラクターが死亡したら、それらを削除します。
さらに、キャラクターに何をすべきか、どこに行くべきかなどを伝えることができる「AI」システム。これは他の多くのシステムと相互作用し、それらに基づいて決定を行う必要があります。繰り返しますが、死んだ文字は実際には何もしていないため、おそらくこのシステムから削除できます。
「名前」システムと「ファミリーツリー」システムは、キャラクター(生きているか死んでいるか)をメモリに保持しているはずです。このシステムは、キャラクターの状態に関係なく、その情報を呼び出す必要があります。(私たちが彼を葬った後でも、ジムはまだジムです。)
これには、システムがより効率的に反応するときに変更するという利点もあります。システムには独自のタイマーがあります。一部のシステムは迅速に起動する必要がありますが、そうでないシステムもあります。ここから、ゲームを効率的に実行する方法について説明します。ミリ秒ごとに天気を再計算する必要はありません。おそらく5か月ごとに行うことができます。
また、よりクリエイティブなレバレッジを提供します。AからBへのパスの計算を処理できる「パスファインダー」システムを構築でき、必要に応じて更新できるため、ムーブメントシステムが「どこに必要なのか」と言うことができます。次に行きますか?」これらの懸念を完全に分離し、より効果的に推論することができます。ムーブメントはパスを見つける必要はありません。そこにたどり着くだけです。
システムの一部を外部に公開する必要があります。あなたのPathfinder
システムではおそらくが必要でしょうVector2 NextPosition(int entity)
。このようにして、これらの要素を厳密に制御された配列またはリストに保持できます。より小さなstruct
型を使用できます。これにより、コンポーネントをより小さな連続したメモリブロックに保持できるため、システムの更新を大幅に高速化できます。(特に、システムへの外部の影響が最小限の場合は、のような内部状態のみを考慮する必要がありますName
。)
しかし、これを強調することはできません。タイル、オブジェクトなどを含むEntity
は単なるID
です。エンティティがシステムに属していない場合、システムはそれを追跡しません。これは、「ツリー」オブジェクトを作成し、それらをSprite
とMovement
システムに格納し(ツリーは移動しないが、「位置」コンポーネントがある)、それらを他のシステムから遠ざけることを意味します。ペーパードリングを除いて、ツリーのレンダリングはキャラクターと同じなので、ツリーの特別なリストは必要ありません。(Sprite
システムが制御できるのか、システムが制御できるのかPaperdoll
。)これで、NextPosition
少し書き直すことができます:Vector2? NextPosition(int entity)
、そして、null
気にしないエンティティの位置を返すことができます。これを私たちのにも適用します。木や岩にNameSystem.GetName(int entity)
戻りますnull
。
私は近くにこれを描きますが、ここでの考え方はあなたにECSにいくつかの背景を与えることです、そしてあなたができるか、本当にそれはあなたのゲームのよりよい設計を与えるために活用しています。パフォーマンスを向上させ、無関係な要素を分離し、より整理された方法で物事を維持できます。(これは、F#やLINQなどの関数型言語/セットアップともペアリングします。まだ行っていない場合はF#をチェックすることを強くお勧めします。C#と組み合わせて使用すると、非常にうまくペアリングできます。)