はじめに
この記事は、Unreal Engine (UE) Advent Calendar 2025の14日目の記事です。
今回はStateTreeからBehaviorTreeを呼び出す方法を紹介します。
StateTreeは状態遷移を管理することに優れており、最近の公式サンプルでもBehaviorTreeに代わってAIを実装するのに使用されています。
しかし細かな状態が増えると状態遷移が複雑になることは想像に難くないです。FF15の意思決定ツールでは、ざっくりと大まかな状態遷移の管理をStateTreeで行い、各状態の具体的な行動をBehaviorTreeで行うといった役割分担をしているそうです。今回はその初歩的なものをやってみます。
環境
Windows11
UE5.6(Launcher版)
下準備
UE5.6でThird Person Template(Combat)を作成して、この中にあるAI用のCharacterとControllerを利用します。
StateTreeを作成します。今回AIControllerにStateTreeを持たせたいので「StateTree AI Component」を選択します。
作成したStateTreeを開き、AIControllerとContextActorを設定します。
AIController Class : BP_CombatAIController
Context Actor Class : BP_CombatEnemy

次にAIControllerの設定です。BP_CombatAIControllerを開きます。
StateTreeAI Componentを追加します。

追加したコンポーネントを選択して、Detailsから先ほど作成したStateTreeアセットを設定します。

最後にClass Defaultsの「Start AILogic on Possess」をオフにしておきます。この項目と、StateTreeAIコンポーネントの「Start Logic Automatically」どちらもオンになっていると二重に実行されます。

AIControllerの実装
AIControllerでは、受け取ったBehaviorTreeアセットを実行する関数と、BehaviorTreeが終了したことを通知するためのイベントディスパッチャーを用意します。
関数については、RunBehaviorTreeを実行するだけです。

StateTreeの実装
Stateの作成
まずは必要なStateを追加します。今回は紫色をBehaviorTreeとして処理を実行しているState、緑色をStateTreeとして処理を実行しているStateというイメージでやっています。
(「Move」StateでBehaviorTreeを呼び出すようにしても問題ないです)

「Move」と「Idle」は確認用にテキスト表示したりDelayを入れているだけなので説明は割愛します。一応「Idle」は下画像のようなTransitionを入れています。

「RunBehaviorTree」Stateには、BehaviorTree実行用のカスタムタスクと、終了待機できるようにTransition設定をしています。次はこのカスタムタスクを作成します。
カスタムタスクの作成
カスタムタスクを作成するには、StateTree内の「NewTask」から「State Tree Task Blueprint Base」を選択するのが楽です。

名前と保存先を決めて作成したタスクを開きます。
まずはAIControllerを受け取るための変数を作成して公開します。

次に関数のオーバーライドで「EnterState」と「ExitState」を作成します。

「EnterState」ではAIControllerに実装したBehaviorTreeを実行する関数を呼び出し、イベントディスパッチャーをBindしています。引数に渡すBehaviorTreeアセットはこれから作成します。
「ExitState」ではUnBindする処理だけしています。

BehaviorTreeの実装
最後の実装です。今回はプレイヤーの方を向いて追いかけてくるだけのシンプルなものを作成します。主旨とは外れるため細かい説明は割愛させていただきます。
作成したBlackBoardは以下です。プレイヤーの参照を持つためのKeyだけ追加しました。

BTT_GetPlayerInfoでは、プレイヤーの参照をBlackBoardのKeyに登録しています。

BTT_FinishBTでは、BehaviorTreeの処理が終了したことを通知して、「StopLogic」でBehaviorTreeを停止しています。この停止処理を入れないと、再びStateTree側でBehaviorTreeを実行しようとしたときに上手くいきません。

パッと見、「StopLogic」を呼ぶとStateTreeの処理も止まってしまう気がするのですが、StateTreeとBehaviorTreeは別々のコンポーネントシステムなので問題ないです。

作成したBehaviorTreeアセットを、StateTreeで作成したカスタムタスク内の関数の引数に設定したら実装は完了です。
完成!
これでStateTreeからBehaviorTreeを動かす仕組みができました!
NavMeshBoundsVolumeとBP_CombatAIEnemyをレベルに配置して動かした例です。

おわりに
FF15の意思決定ツールに憧れて今回の記事を書いてみました。何やっているか気になる人は参考文献に載せてあるのでご覧ください。
今度は逆にBehaviorTreeからStateTreeを呼び出せるようにして、もう少しまとまった仕組みを作りたいですね。
参考文献
書籍
GDCでの講演まとめ記事
論文




