エンティティシステムの多くの動きの原因


9

私はエンティティシステムのアイデアにかなり慣れていません。たくさんのものを読んだことがあります(最も便利なのは、この素晴らしいブログこの回答)。

未定義の数のソースによってオブジェクトの位置を操作できるほど単純なものを理解するのに少し問題があります。

つまり、私にはエンティティがあり、これには位置コンポーネントがあります。次に、このエンティティに、指定された時間内に指定された距離を移動するように指示するイベントをゲームで実行します。

これらのイベントはいつでも発生する可能性があり、位置と時間の値は異なります。その結果、それらは一緒に合成されます。

従来のOOソリューションでMoveByは、距離/時間を含むある種のクラスと、ゲームオブジェクトクラス内のそれらの配列がありました。各フレームではMoveBy、すべてのを反復処理して、位置に適用します。がMoveBy終了時間に達した場合は、アレイから削除します。

エンティティシステムでは、この種の動作をどのように再現するべきかについて少し混乱しています。

一度にこれらの1つだけがあった場合、それらを一緒に合成することができる代わりに、それはかなり単純で(私は信じます)、次のようになります。

PositionComponent 含む x, y

MoveByComponent 含む x, y, time

Entitya PositionComponentとaの両方があるMoveByComponent

MoveBySystemこれらのコンポーネントの両方を持つエンティティを探し、の値をMoveByComponentに追加しますPositionComponent。にtime到達すると、そのエンティティからコンポーネントが削除されます。

多くの移動方法で同じことをどのように行うかについて、私は少し混乱しています。

私の最初の考えは、私が持っているだろうということです:

PositionComponentMoveByComponent上記と同じ

MoveByCollectionComponentMoveByComponentsの配列が含まれています

MoveByCollectionSystemこれは、a PositionComponentとa を持つエンティティを探し、その内部MoveByCollectionComponentMoveByComponentsを繰り返し、必要に応じて適用/削除します。

これはより一般的な問題だと思います。同じコンポーネントの多くがあり、それぞれに対応するシステムが動作することを望んでいるからです。私のエンティティには、コンポーネントタイプ->コンポーネントのハッシュ内にコンポーネントが含まれているため、エンティティごとに特定のタイプのコンポーネントが1つだけ存在します。

  1. これはこれを見るのに正しい方法ですか?

  2. エンティティは常に特定のタイプのコンポーネントを1つだけ持つ必要がありますか?


1
MoveBy機能はまるでベロシティのような音ですね。順調に進んでいるようですね。2番目の質問については、エンティティ/コンポーネントシステムのさまざまな実装がたくさんあります。あなたがリンクした私の回答で説明されているものは、特定のタイプのコンポーネントを1つだけ持っています。
MichaelHouse

少し違いますが、この速度はある時間から別の時間までしか有効でなく、それらの多くは一度に合成することができます。ある程度の安心が必要だったと思います。過去に私のゲームはOO(厳密に言えばほぼ)OOでした-同じプロジェクトの何年か後に、私たちの制作速度が低下しました-これは恐ろしくなじみのない領域です;) 。ちなみに、別の投稿でのすばらしい回答は、いくつかの問題を解決するのに役立ちました
Sticky

私は次のようにします:キーボードクリックまたはAIでモバイルがどこかに移動する必要があると考えて、MobileBehaviorComponentがどこかに移動する必要があると格納する(モバイルアクション用のFSMが内部にある)ことをMobileBehaviorComponentに通知するPlayerInputComponentおよびAIInputComponent(またはシステム)があります。一部のシステムはそれを移動します。粒度が高すぎるため、Transform、Model、Light、Mobなどの上位レベルのコンポーネントはすべて同様に機能します。また、コンポーネントを削除する必要はありませんでした。それらは、ゲームオブジェクトを説明するものに似ているため、単に消えることはありません。
Kikaimaru

この特定のMoveByの例は単なる例です。問題は、そのように物事をどのように組み合わせるかということでした。「5秒でx = 5とy = 6で移動」、「10秒でx = 10 y = 2で移動」と具体的に言う必要がある場合、これはどのように行うのですか?
スティッキー

「複合」とはどういう意味ですか?速度を追加するような?それで、あなたが調合move x by 10 in 2 secondsしてmove x by -10 in 2 seconds、実体が完全にまだ立っているなら?
Tom Dalling、

回答:


6

シナリオでは、通常、3つのコンポーネントをゲームオブジェクトに追加します。

  1. TransformComponent(位置、方向、スケール)
  2. VelocityComponent(速度、方向)
  3. ControllerComponent

ゲームオブジェクトが、説明したようにパスに沿って移動するなど、ある種のAI機能を必要とする場合、AIControllerをそのコンポーネントのリストに割り当てます。AIControllerは、ビヘイビアーツリーをステップするラッパーにすぎません。ビヘイビアツリーは、ゲームオブジェクトに実行させたい実際の機能を設計する場所です。

BehaviorTree* tree(new SequentialNode());
tree->addChild(new MoveToNode(x,y,z));
tree->addChild(new WaitNode(30));
tree->addChild(new MoveToNode(a,b,c));
tree->addChild(new WaitNode(30));
gameObject->addComponent(new AIController(tree));

AIサブシステムはAIControllerを管理するため、サブシステムがコントローラーをティックし、コントローラーが動作ツリーをステップします。MoveToNode()は現在の位置/方向を調べ、コンストラクターの引数に基づいて移動先の方向ベクトルと速度を計算し、速度コンポーネントに値を設定します。運動システムは、値を持つ運動コンポーネントを読み取り、物理を適用することにより、位置/方向を適宜更新します。

上記のコードは、ゲームオブジェクトをスポーンの場所からワールドスペース内のx、y、zに移動し、最低30秒待ってから、ゲームオブジェクトを場所a、b、cに移動してから、さらに30秒待機します。待機が終了すると、動作シーケンスが終了したため、最初から繰り返します。

これにより、エンティティサブシステムへの影響を最小限に抑えながら、必要なすべてのAI機能をAIサブシステムにすべて含めることができます。また、エンティティシステムのコンポーネントリストを細かく保つことなく細かく保つこともできます。


1

オプションは、コントローラーをデザインに追加することです。エンティティは位置を表すデータを所有しています(私のエンジンの場合、以前の位置も記憶するデータがあるため、速度ベクトルと、それらが移動またはテレポートされているかどうかを知ることができます)が、物理については何も知りません。 AI。コントローラはエンティティを移動し、同じエンティティに影響を与える多数のコントローラ、またはさまざまなエンティティに影響を与える1つのコントローラを持つことができます。

たとえば、run()メソッドを使用して基本コントローラクラスを作成するか、名前が気に入らない場合はthink()、update()、またはtick()と呼びます。次に、それを継承して、MoveController、NPCController、PlayerInputController(プレーヤーエンティティ用)、PhysicControllerを作成します。次に、run()メソッドを実装します。私はあなたのMoveByComponentをエンティティではなくMoveControllerに置きます。

これらのコントローラーは、エンティティー固有のデータを保持している場合、各エンティティーによってインスタンス化できます。それらは、後で再利用するために破棄またはリセットできます。また、RTEゲームなどでエンティティのグループを移動するためにコントローラーを使用することもできます。たとえば、さまざまなユニットをグループとして移動する必要がある場合、各ユニットごとにコントローラーがゲームのパフォーマンスを低下させる可能性があるため、すべてのユニットを割り当てることができます。 GroupControllerまたはLegionControllerに追加し、組織化されたグループの一部としてユニットを移動させます。戦うときに、ゲームが個々のユニットの動作を許可し、おそらくほとんどのゲームが許可する場合は、UnitControllerに切り替える必要がありますが、最初からではなく、必要なときにのみ実行することをお勧めします。

私の開発中のゲームには、パスに従ってエンティティを移動するMoveControllerがあり、NPCとプレイヤーキャラクターごとに1つのMoveControllerが存在します。時々、プレイヤーが押すことができるボックスまたはロック用に作成されます。PhysicController、1つのインスタンスのみ、それに割り当てられたすべてのエンティティの位置をチェックします。あるエンティティが別の割り当てられたエンティティと衝突した場合、両方の結果の位置が計算されます(実際にはそれ以上のことが行われますが、アイデアがわかります)。NPCControllerはAIであり、NPCごとに1つのインスタンスです。NPCの状況をチェックし、どこに移動するかを決定し、実際にNPCを移動するMoveControllerにパスをプッシュします。コントローラーには優先順位があるため、事前に順序を決定できます。PhysicControllerが最後に実行されます。

私はコントローラーを推奨しますが、「正しい」唯一のオプションではありません。たとえば、エンティティ自体にthink()メソッドを持つCafuエンジンのEntityインターフェースを覚えています。クラスのユーザーはEntityから継承してthink()を実装する必要があります。CompanyBotという派生クラスを覚えています(例に付属しています)ゲーム)そのメソッドでいくつかの衝突チェックを行います。これは「考える」と呼ばれるため、AIコードもそこにあると予想されると想定できます。NeoAxisエンジン(前回調べたところ)はAIと物理をエンティティから分離しています。

私が聞いたコントローラーパターンが存在します。多分あなたはそれを検索するべきです、そしてそれはおそらくここで私が話していることと正確には同じではありませんが、良い解決策のようにも聞こえます。


これは基本的に、現在私たちが既に持っているOO設計です。エンティティ、派生物(キャラクター、モンスター)などで、私はほぼ2年間このゲームにフルタイムで取り組んできた私たちのチームを主導してきました。 codebase-そして、新機能を出荷するのに恥ずかしいほど長い時間がかかり始めています。エンティティシステムのアイデアはまさに私が探しているもののようです。そのため、あなたの答えはあまり関連性がありませんが、質問の上部にあるリンクを自分で読んで、それらがあなたを助けることができるかどうか確認してください:)
スティッキー

@Stickyコンポーネントで構成されたNode System plus Entityは、進化したバージョンのように提案されたコントローラーアプローチとは異なる必要なシステムを表現する賢い方法であることを認めなければなりません。結局のところ、あなたは本当に私の答えを必要としません。
羽生はるる

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