有限状態マシンをコンポーネントベースのアーキテクチャに配線する方法は?[閉まっている]


23

ステートマシンは、コンポーネントベースのアーキテクチャで有害な依存関係を引き起こすようです。

具体的には、状態マシンと状態関連の動作を実行するコンポーネントとの間の通信はどのように処理されますか?

私がいる場所:

  • コンポーネントベースのアーキテクチャは初めてです。
  • 私は格闘ゲームを作っていますが、それは重要ではないと思います。ステートマシンを使用して、「クラウチング」、「ダッシュ」、「ブロッキング」などの状態を切り替えることを想定しています。
  • この状態管理手法は、コンポーネントベースのアーキテクチャにとって最も自然なシステムであることがわかりましたが、これまでに読んだ手法とは矛盾しています: 可変動作文字の動的ゲームオブジェクトコンポーネントシステムすべてのコンポーネントをアクティブ化/非アクティブ化することをお勧めしますアクティベーションの条件を継続的にチェックすることにより、自分自身。
  • 「実行中」または「ウォーキング」などのアクションは状態として理にかなっていると思います。これは、https//gamedev.stackexchange.com/a/7934で受け入れられている応答とは一致しません
  • これは便利ですが、あいまいです。コンポーネントベースのゲームアーキテクチャに動作を実装する方法は?ステートマシンのみを含む別のコンポーネントを使用することをお勧めします。ただし、これには、ステートマシンコンポーネントと他のほぼすべてのコンポーネントとの間に何らかの結合が必要です。このカップリングがどのように処理されるべきか理解できません。これらはいくつかの推測です:

    A. コンポーネントはステートマシンに依存しますコンポーネントは、列挙定数を返す
    ステートマシンコンポーネントへの参照を受け取りますgetState()。コンポーネントは定期的に自身を更新し、必要に応じてこれを確認します。

    B. ステートマシンはコンポーネントに依存します。
    ステートマシンコンポーネントは、監視しているすべてのコンポーネントへの参照を受け取ります。getState()メソッドを照会して、どこにいるかを確認します。

    C. それらの間のいくつかの抽象化
    イベントハブを使用しますか?コマンドパターン?

    D. コンポーネントを参照する個別の状態オブジェクト状態
    パターンが使用されます。コンポーネントのセットをアクティブ化/非アクティブ化する個別の状態オブジェクトが作成されます。状態マシンは状態オブジェクトを切り替えます。

  • アスペクトの実装としてコンポーネントを見ています。彼らはその側面を実現するために内部的に必要なすべてを行います。コンポーネントは、他のコンポーネントに依存せずに、単独で機能する必要があるようです。いくつかの依存関係が必要であることは知っていますが、ステートマシンはすべてのコンポーネントを制御したいようです。

回答:


7

概要はかなり簡単ですが、昨年New Game Confで行ったプレゼンテーションのスライドをご覧ください。

https://docs.google.com/presentation/d/110MxOqut_y7KOW1pNwIdcccisIA3ooJwVR-xm-ecuc4/view

(以下の関連画像を参照)

このテクニックの要点は、アクションリストパターン(スライドで説明されているが、やや不十分)を、コンポーネントベースのゲームエンティティに作用する動作状態マシンと組み合わせることです。

本質的には、単純なAIシステムに必要な種類の行動間統合を対象とした、AI動作専用の特別な構成システムを作成することと同じです。

その特定のゲームの私のお気に入りの部分は、事前に記述された動作のリストから選択するだけで、まったく新しいタイプの敵を作成し、ゲームオブジェクトのアクションリスト(BrainComponentにある)を希望の順序で配置する方法でした優先順位、そしてすべてがうまくいった。Blocking / NonBlockingアクションを許可するアクションリストを使用すると、実装がどれほど簡単であるにせよ、非常にクールなことができます。

実際にはStunBehaviorActionだけがアクションリストスタックの一番上にプッシュされる「スタン」などの動作です。スタン動作がアクティブになった場合(ゲームオブジェクトのEarsComponentが衝撃的な衝撃波を聞いたことを確認した後)、内部状態をStunnedに設定し、アニメーションコンポーネントにスタンアニメーションを再生するように指示し、アクション状態をBlockingに設定し、タイマーをゲームオブジェクトのEnemyParametersComponentから取得したスタンタイムアウト。これはブロッキングであり、アクションリストの一番上にあるため、アクションリスト内の他のBehaviorActionはどれもupdateメソッドが呼び出されないため、基本的にオフになります。タイムアウトが経過すると、StunBehaviorActionは状態をアイドルに戻し、アクション状態をNonBlockingに戻します。

私たちが実装した他の動作は、ほとんどすべて単一の内部状態マシンで実装されました。実際、ステートマシンを持たない2つは、PatrolPathBehaviorAction(アイドル状態の場合は一連のPathActionをアクションリストにプッシュし、それがMoveActionをプッシュする)とGuardHomeBehaviorAction(常にアクションリストを使用し、常にPathActionを敵のホームロケーションにプッシュするだけです。他のすべての動作はステートマシンでした。

スライド10 スライド25 スライド26


「行動」と「アクション」の根本的な違いは何ですか?
子犬

1
@Pup:コードの観点から、私がそれを構築したとき、振る舞いはアクションです。概念的な観点から、アクションは通常一時的なものであり、「完了」するまでしか存在しませんが、ビヘイビアは永遠に存在し、リストから削除されることはありません。別のチームが同様のシステムを構築しましたが、アクション用とビヘイビア用の2つのリストがあり、十分に機能します。ただし、ビットマスクとグループ化を使用して、アクションが特定の動作をブロックする機能を持つことが好きです(レーン、私はスライドでそれらを呼び出したと思います)。中央のスライドのグラフィックが非常に悪いのでごめんなさい。:)
ショーン・ミドルディッチ

3

私が働いていた前の会社では、状態ベースのAIを備えたコンポーネントベースのシステムがありました。そのオブジェクト/ユニットのすべての動作を制御するAIコンポーネントがありました。さまよう、攻撃など、AIがアクティブな場合、AIは必要なロジックを実行するために各フレームの更新を受信します。AIがアイドリングまたは移動していない場合、コンポーネントは非アクティブ化され、各フレームが更新されませんでした。コンポーネントは、非アクティブ化されている間、イベントベースのメッセージを受信する可能性があるため、プレーヤーがアグロ半径を入力するなどのメッセージを受信し、フレームベースの更新を実行できるようにAIコンポーネントを再アクティブ化することで応答できます。

AIコンポーネントにはサブコンポーネントがあり、実行中のアクションのタイプに基づいて、オンザフライで作成および破棄できます。たとえば、放浪している場合、放浪中のサブコンポーネントを作成し、放浪中に各フレームを更新します。放浪中にアグロ化すると、そのサブコンポーネントを閉じて攻撃サブコンポーネントを開きます。AIコンポーネントは、オブジェクト上の他のすべてのコンポーネントから独立している必要があります。たとえば、ユニットの移動値を単純に照会する入力コンポーネントがありました。それが行ったクエリは、人間とAIオブジェクトの両方が応答するものでした。これにより、AIコンポーネントは、人間の制御可能なコンポーネントが入力コンポーネントが取得できる値を設定するのと同じように、入力コンポーネントが取得できる放浪などの間に自身に移動値を設定することができました。


それでは、AIサブコンポーネントが実際に作業を行っていますか?AIコンポーネントと同じレベルで、エンティティコンポーネントとして存在していましたか?
子犬

エンジンのサブコンポーネントは、ベースコンポーネントクラスの一部でした。したがってComponent、から派生したanyは、その上にBaseComponent任意の数のSubComponentsを持つことができます。のUpdate()メソッドはBaseComponent、サブコンポーネントのリストをチェックし、Update()それらを呼び出します。Subcomponentsは完全にオプションであったため、BaseComponent何もない可能性があります。また、コンポーネントに送信されたメッセージはサブコンポーネントにもルーティングされました。
ニックフォスター

1

具体的な例がなく、用語が非常に曖昧であるため、コンポーネントが何を意味するのか少しわかりません。多くの場合、ゲームエンティティは、継承ではなく構成を使用して構築されます。したがって、エンティティにヘルスコンポーネントを追加することでダメージを受ける可能性のあるものにしたり、アニメートコンポーネントを追加してアニメートすることができます。AIをそのようなコンポーネントに配置することもできます。AIコンポーネントには意思決定ロジックがあり、それをシステム内の他のコードの多くに結合することを懸念している場合は、AIロジックのみがアクセスを許可されている黒板に情報を収集できます。AIシステムの出力への依存関係の問題もあります。基本的に、AIはエンティティを制御しており、その制御にはインターフェイスが必要です。便利な概念の1つは、コントローラーまたはゲームパッドの概念です。AIは、プレイヤーのゲームパッドが埋めるのと同じような構造を埋めることができます(ただし、特定の機能のための追加の「ボタン」がある場合があります)。これで、この構造をアニメーションコンポーネントに渡して、それを解釈し、再生する適切なアニメーションを選択できます。異なるAIサブコンポーネントは、構造の異なるフィールドまたは異なる優先度の同じフィールドに書き込むことさえできます。たとえば、照準と歩行。異なるAIサブコンポーネントは、構造の異なるフィールドまたは異なる優先度の同じフィールドに書き込むことさえできます。たとえば、照準と歩行。異なるAIサブコンポーネントは、構造の異なるフィールドまたは異なる優先度の同じフィールドに書き込むことさえできます。たとえば、照準と歩行。

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