概要
StateTree は汎用の階層型ステート マシンで、ビヘイビア ツリーの セレクター とステート マシンの ステート および 遷移 を組み合わせたものです。ユーザーは整理された高性能のロジックを柔軟に作成できます。
StateTree にはツリー構造に整理されている各ステートが含まれます。ステートの選択はツリーのどの場所でもトリガーできますが、まずルートから始めます。選択プロセス中に、各ステートの 入力条件 が評価されます。合格すると、選択は利用できる場合にステートの子ステートに進みます。子ステートが利用できない場合、現在のステートがアクティブ化されます。
ステートの選択により、ルートからリーフ ステートまですべてのステートがアクティブ化されます。各ステートは タスク と 遷移 で構成されます。
ステートが選択されると、選択されたステートとそのすべての親ステートはアクティブになります。すべてのタスクは、ルートから始まり、選択したステートまで下り、すべてのアクティブ ステートに対して実行されます。
各タスクは StateTree への出力を提供します。よくある出力の例には、ターゲットを選択、アニメーションをプレイ、オブジェクトを見ることがあります。各ステートには複数のタスクを設定でき、ステートのすべてのタスクは、ステートがアクティブである限り同時に実行されます。実行が完了した最初のタスクは遷移をトリガーし、結果として新しいステートの選択につながります。
シンプルな例としては、StateTree を使用した時刻システムの作成が挙げられます。各時刻のステートを作成し、各ステートの配下に個別のタスクを作成します。各タスクは異なる要素、フォグ密度、天球の色などを処理できます。
別の例はレベルを歩き回る AI エージェントを設定し、見回している間に常にヒットがあるかどうかをチェックします。歩行と見回りのステートを作成し、ヒットに反応する別のステートも作成できます。
StateTree での遷移は、ツリーの他のステートを指すことができます。遷移には トリガー条件 があり、遷移がステート選択プロセスをトリガーする前に満たす必要があります。
ステートの選択が成功すると、新しいステートが選択されます。定期的にモニターされる遷移もあれば、ステートの完了時のみ実行される遷移もあります。リーフ ステートから遷移が評価され、ルートに向かって上に進んでいきます。このプロセスの間に、成功し、ステート選択につながる最初の遷移が選択されます。この階層では、共通の遷移をグループ化できます。
これらは StateTree の異なる要素です。
番号 | StateTree の要素 | 説明 |
---|---|---|
1 | ルート | StateTree の実行が開始したときに選択される最初のステート。 |
2 | セレクター ステート | 子ステートがあるステートを指します。このステートは直接選択されません。子ステートの 1 つが選択されています。 |
3 | ステート入力条件 | ステートを選択できるかどうかを決定する条件リストを指します。 |
4 | タスク | ステートがアクティブになったとき、ステートに含まれ、実行されるアクションのセットを指します。 |
5 | 遷移 | ステート選択プロセスをトリガーする諸条件を定義します。タスクが完了、成功または失敗したとき、もしくはモニターされた条件が成功したときに、遷移がトリガーされます。 |
選択フロー
新しいステートを選択する
StateTree は、ビヘイビア ツリーと同様に、アクティブ ステートを選択します。ステート選択は最初のティックでルートから始まり、ツリーの配下で各ステートの入力条件を評価していきます。
- 入力条件に合格しない場合、選択は次の兄弟ステートに移ります。
- 入力条件に合格し、ステートがリーフ ステートである場合、新しいステートとして選択されます。
- ステートに子ステートがある場合、リーフ ステートが見つかるまで、最初の子ステートで同じプロセスが続けられます。
ステートに子ステートがあるものの何も選択できない (それらの入力条件が失敗する) 場合、すべての入力条件がテストに合格している場合でも、ステートが選択されません。
ビヘイビア ツリーとステート マシンの大きな差の一つは、ツリーを下って実行していきながら、ステート マシンはステートを一般に選択しますが、一方ビヘイビア ツリーは適切なリーフ ノードを見つけようとします。
一般には、ビヘイビア ツリーは、ステートが選択されているときでも、ステート選択ロジックの実行を続けます。これはステート間を遷移する唯一の方式です。
StateTree は遷移に基づいて、オンデマンドでステート選択プロセスを実行します。最初のティックで、最初のステートを実行するために選択する、ルート ステートへの暗黙の遷移があります。ステートが選択されると、遷移により、選択ロジックが実行される場所とタイミングが決まります。
ステート タスクを実行する
ステートが選択されると、そのすべてのタスクは同時に実行を開始します。遷移が選択プロセスをトリガーし、ステートが選択されるまで、タスクは実行を続けます。選択されたステートは現在のステート (ステートが引き続き実行) または新しいステートです。
最も一般的な変遷トリガーは completion (完了) で、アクティブ ステートの最初のタスクが終了したときに、実行されます。他の遷移は Tick (ティック) としてマークでき、各ティックでテストされます。条件付き遷移がテストに合格すると、ステート選択ロジックが実行され、選択プロセスがターゲット ステートで開始されます。ターゲット ステートに子ステートがあると、選択プロセスは選択ロジックの一部として、子ステートを考慮します。
データ フロー
State Tree は、データ バインディングでツリー内でデータを渡します。データ バインディングを使用すると、条件を作成したり、実行するタスクを構成したりできます。また、それにより、State Tree に渡されたデータ、または特定の方法でノード間で渡されたデータにアクセスできます。
State Tree のすべてのノードで使用できる一般的なデータ型は次のとおりです。
データ型 | 説明 |
---|---|
State Tree のパラメータ | ユーザーは、State Tree の実行中に参照できる入力パラメータを State Tree に追加できます。これらのパラメータにより、使用方法に応じてツリーの使用方法をカスタマイズできます。たとえば、ユーザーは、ゲームプレイ中に使用するために外部からツリーに渡すことができるアニメーション アセット パラメータを定義できます。 |
コンテキスト データ | コンテキスト データは、選択した State Tree スキーマに基づいて State Tree で使用可能な定義済みのデータを参照します。これは、State Tree が使用されている場所によって変化します。たとえば、アクタによって使用されている State Tree は、そのアクタをコンテキストとして持ちます。ただし、同じ State Tree がスマート オブジェクト動作で使用されている場合、コンテキストは使用されるスマート オブジェクトとそれを使用するアクタを参照します。 |
エバリュエーター | エバリュエーターを使用すると、他の方法ではパラメータまたはコンテキスト データでは実行できないデータを State Tree に公開できます。エバリュエーターは、実行時に State Tree で実行可能な個別のクラスです。エバリュエーターには変数が含まれており、ツリーの開始時、停止時、および各ティックでカスタム コードを実行できます。エバリュエーターのプロパティは、パラメータまたはコンテキスト データ、またはエバリュエーターのリストの前にある他のエバリュエーターにバインドできます。 |
グローバル タスク | グローバル タスクを使用すると、Tree Start イベントと Tree Stop イベントとの間で有効なステート ツリー タスクを実行できます。グローバル タスクは、ステート選択に使用できる永続的データが必要な場合に利用できます。たとえば、時刻システムで、現在の時刻を定義するグローバル タスクを作成したりできます。グローバル タスクはツリー内のルート ステートよりも前に開始されるため、この情報はツリーが開始してから最初のステート選択時に使用可能になります。 |
StateTree ノードは、ノード間でデータを共有できます。StateTree の異なる要素は、次の方式でデータにバインドできます。
StateTree の要素 | 要素をバインドできるデータ |
---|---|
入力条件 | すべての親ステートの共通データとタスクにバインドできます。 |
遷移条件 | 共通データ、および現在のステートとすべての親ステートからのタスクにバインドできます。 |
タスク | 共通データ、および現在のステートとすべての親ステートの以前のタスクにバインドできます。 |
ブループリント インテグレーション
StateTree はブループリント スクリプトで実行するように設計されています。次のブループリント クラスを拡張して、カスタムのタスク、エバリュエーター、条件を作成できます。
基本クラス | 説明 |
---|---|
UStateTreeTaskBlueprintBase | StateTree のタスクの基本クラス。 |
UStateTreeEvaluatorBlueprintBase | StateTree のエバリュエーターの基本クラス。 |
UStateTreeConditionBlueprintBase | StateTree の条件の基本クラス。 |
前に説明した例のとおり、StateTree とブループリントを使用して、時刻システムを作成できます。このシステムは時刻に基づいて、レベルのフォグ密度を変更します。時間に関係なく、ライティング条件を変更するため、嵐の呪文もチェックできます。
この例では、次のブループリント クラスを作成できます。
ブループリント クラス | 機能 |
---|---|
タスク | フォグ密度を時間の経過とともに変更します。特定の時刻を表すすべてのステートにこのタスクを追加できます。 |
条件 | 嵐の呪文が投げかけられたかどうかをチェックします。この条件はルート ステートで評価できます。true の場合、特別なストーム ステートに実行を移動します。 |
エバリュエーター | 時刻を遷移および入力条件に公開します。 |
一般パターン
類似タスクをグループ化する
タスクは共通ステートの配下でグループ化できます。前の例では、ワールドでスマート オブジェクトを処理するステートがあります。このステートには、スマート オブジェクトへの到達とスマート オブジェクトの使用を処理する子ステートが含まれます。
これらの子ステートのそれぞれにはステートが選択されたときに実行されるタスクが含まれます。Reach 子ステートには、スマート オブジェクトを見つけ、AI エージェントをスマート オブジェクトに移動するタスクが含まれます。
このグループ化戦略を使用するとき、すべてのタスクはステート経由で同じ遷移を共有します。
シーケンス
StateTree には Next 遷移があり、ステートのシーケンスの作成と整理を簡素化します。
前の例では、Reach ステートが選択されているとき、Find SO Target、Move to SO、および Look の各タスクが実行されます。各タスクが完了すると、Next 遷移により、下にある Use ステートの実行に移動します。ここでそのタスクの実行を開始できます。
失敗時の処理
StateTree は階層方式つまりアクティブ タスクからツリーを上っていって、タスクの完了の失敗を処理します。
前の例では、Reach Slot ステートは成功時に次のステート (Wait) に実行を移し、または失敗時に親ステート (Wait at Intersection) に実行を移します。Wait at Intersection ステートは、子ステートのいずれかが失敗した場合に Idling ステートへの遷移をトリガーします。
Wait ステートは、親ステートが異なるステートを選択するまで、成功または失敗時にそれ自体への実行を無限に続けます。
階層データ
タスクは互いにデータを共有できます。タスクで公開されるデータは、アクティブ ステートに属する他のタスクで利用できます。これにより StateTree でのリソース処理がさらに効率化されます。
前の例では、Crowd Claim Wait Slot タスクは AI エージェントの Smart Object Slot の要求を試し、成功した場合に、Move To Wait Slot タスクに実行を渡します。このタスクは親タスクのスロット位置を使用します。成功した場合、Wait At Slot タスクに実行を渡し、親タスクからスロット位置を同様に使用します。
動作を調整する
StateTree には、状況に応じた動作が簡単に実行できるように、タスクを整理する方法があります。
前の例では、Wait ステートで AI エージェントの起立移動 - ヒットがあるときにAI エージェントが見回して反応することを処理します。デフォルトでは、Wait Look ステートが実行されます。ステートが成功した場合、親に実行が戻ります。ただし、失敗した場合、Wait Hit ステートに実行が移動します。
Wait Hit ステートは Mass LookAt および Mass Contextual Anim タスクを実行します。これらのタスクはヒットに対して適切なアニメーションをプレイします。