コンポーネント/エンティティベースの設計+ビヘイビアツリー=>統合方法


9

私の現在のプロジェクトでは、コンポーネント/エンティティベースのシステムを実装しました。基本的に、このかなり未定義の領域にあるベストプラクティスのほとんどに従っています

だから私は(少し拡張された)エンティティを取得しました。これは基本的にintID、人間が読める名前、std::mapコンポーネントのa 、およびlong存在するコンポーネントを示すために使用される「タイプインジケーター」です(私はenumすべてのコンポーネントに対して2の累乗を持っています)タイプと、コンポーネントがエンティティに追加されるときはいつでも、ビット単位の演算によってその長さを自動的に変更し、比較しますます。この回答を)。

次に、Componentsもあります。これもかなり単純です。コンポーネントタイプとしてのintID enum、親エンティティポインター、およびstd::mapこのコンポーネントが保持するすべてのプロパティのa です。

最後に、実際のロジック処理を処理するいくつかのシステム/マネージャー。彼らは最初に、現在処理されているエンティティに一致するlong「タイプインジケーター」があるかどうかをチェックします=そのシステムに必要なすべてのコンポーネントが存在します。次に、必要に応じていくつかのプロパティにアクセスし、それぞれのコンポーネントの関数を直接呼び出すか、メッセージディスパッチャを介してメッセージを送信します。

結論:ここまでは、かなり標準的なイベント駆動型のコンポーネント/エンティティベースのシステムとデータ駆動型のアプローチを組み合わせたものです(比較すると、コンポーネントにはハードコードされたデータ変数がなく、(一部の)コンポーネントとして一般的なマップがありますコンポーネントの/ archetypesは後で、実際のコンポーネントコードの一部ではない追加データを追加するオプションを使用してファイルから読み取られます。

次に、そのプロジェクトに(AiGameDev BTSKに基づく)動作ツリーも導入したいと思いますが、それらを既存のコンポーネントにリンクする必要があるかどうか、どのようにリンクするべきか、またはそれらのデザインを一般的に統合する方法はわかりません。

いくつかの関連するアイデア/ポイント/質問が頭に浮かびます:

  1. 私のBTはファイルから(再び)読み込まれます。現在BT Action、ツリー内のとアプリケーションの実際のコーディングとの間の接続を最適にする方法を確認するのに苦労しています。BTファイルで使用されるアクション名と実際のロジック実装への関数ポインターとの間に何らかのマップを作成する必要がありますか?それを解決するための通常のアプローチは何ですか?

  2. 私はすべての異なるEntityタイプ(つまり、ゲームロジックとAIに関連するコンポーネントの組み合わせのそれぞれについて、何度も言及した長い「タイプインジケーター」で示されるように)に対してBTを作成する必要があると思います。結果として、BT Actionアクションごとに多くのコンポーネントが関与する可能性が最も高いため、コンポーネントに実装を配置することは意味がありませんか?

  3. それで、BT Actionロジックは複数の個別のシステムに配置する必要がありますか(アイデア#1からのマップが指し示すメソッドに)。次に、システムは私のlong「タイプインジケーター」ごとにEntity、BTが現在チェックされており、特定のアクション(=システム内のメソッド)の実行が実際に許可されている(=必要なコンポーネントがある)かどうかをチェックします。しかし、そうでない場合(たとえば、BT作成者が特定の状況を見落とし、実行時に必要なコンポーネントがエンティティにアタッチされなくなる可能性があるため)、何も起こりません。

質問:

  • そのような統合のための実証済みの概念はありますか?
  • 上記の3つの点についてどう思いますか?
  • コンポーネント/エンティティベースのデザイン全般に関して、他に思い浮かぶことはありますか?

要点1:行動ツリーは、主にキャラクターの行動を作成するために使用される視覚的なDSLにすぎません。BehaviorTreeコンポーネントは、スクリプトコンポーネントの場合よりも多くのこと、または少ないことを行うべきではありません。ポイント3:通常のフィールドにマップを使用する理由は何ですか?
Eric

#1:この文脈で「DSL」は何を表していますか?#3:すみませんが、これについてはフォローできません。どういう意味か説明してください。
フィリップアルガイエ2013年

1
おそらくドメイン固有言語、つまり 非常に具体的な問題を処理するカスタム構文。
Patrick Hughes

パトリックは正解ですが、セマンティクスもその一部であり、この定義から「非常に」除外される可能性があります。-Re 3:私の謝罪、それは読む必要があります:「コンポーネントの通常のフィールドマップを使用する理由は何ですか?」
Eric

Re 3:後でC ++コードの外で追加のプロパティを動的に指定する機能が必要です(流行語:データ駆動型)。簡単にするために、私は(少なくとも今のところ)すべてのプロパティを(マップを使用して)この一般的なフレームワークに配置しています。パフォーマンスの問題が発生した場合は、後で再検討する必要があるかもしれません...
フィリップアルガイエ2013年

回答:


2

現在、ツリー内のBTアクションとアプリケーションの実際のコーディングとの間の接続を最適化する方法を見つけるのに苦労しています。BTファイルで使用されるアクション名と実際のロジック実装への関数ポインターとの間に何らかのマップを作成する必要がありますか?それを解決するための通常のアプローチは何ですか?

関数ポインタを忘れて、オブジェクトについて考えます。動作ツリーの各ノード(この時点以降のBT)は、コード内の1つのオブジェクトに対応するのが理想的です。これらのオブジェクトには、それらをツリーとして配置し、トラバースするための標準インターフェイスがあります。一連の関数ポインターは動作には問題ありませんが、ツリーの構造をまったくキャプチャしません。

結果として、BTアクションの実装をコンポーネントに配置することは意味がありません。アクションごとに多くのコンポーネントが関与する可能性が高いからです。

エンティティには、そのエンティティのBTに関連するデータを格納する単一のBehaviorTreeコンポーネントが必要です。BTの実行は、システム内のコンポーネントの処理方法に応じて、BTコンポーネントまたはBTサブシステムによって実行されます。コンポーネントを使用するほとんどの場合と同様に、ジョブを実行するには他のコンポーネントを参照する必要がありますが、それらの他のコンポーネントはBTについて何も知る必要はありません。

使用可能なさまざまなアクションは、最も単純なレベルでは、さまざまなBTノードオブジェクトにエンコードされます。それらは、必要に応じてコンポーネントを操作することにより、関連するエンティティを動作させることができるはずです。移動する移動コンポーネントにアクセスします。


パラグラフ#1:はい、BT自体がオブジェクトになります(AiGameDevのバージョンのように言ったように)。アクションそのもののファンクタについて考えていたのですが、あなたのパラグラフ#2がそれを変えました。どういうわけか、この本当にシンプルなアプローチは私には決して起こりませんでした(エンティティは独自のBTメンバーインスタンスを持っています)。まったく新しいコンポーネントのせいか、もう単純で単純だとは思わなかったので、コンポーネントをBTのものと混合する方法を探していましたが、実際には必要ありません。
フィリップアルガイエ2013年

私が以前に失っていた主なことは、アクションをエンティティに関連付ける方法でした。これで明確になりました。アクションは、ツリーを介してどのエンティティを認識するかを返します。
フィリップアルガイエ2013年

@フィリップ・アルガイエ気になるのですが、どうやってBTノードを作成したのですか?1ビヘイビアノード= 1エンティティ(1つのゲームオブジェクトごとに多数のエンティティになる)としてノードを作成しましたか、それとも通常のクラス(ECS関連ではない)としてノードを作成しましたか、それとも他のアプローチを使用しましたか?感謝!
cppBeginner 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.