うどんてっくメモ

技術的なメモをまったりと

【Godot】Beehaveを使ったBehaviour Treeの構築

はじめに

本記事で紹介および検証を行なっているツール、ライブラリのバージョンは次の通りです。

  • Godot Engine v4.4.1.stable.official
  • Beehave v2.9.0

バージョンによっては挙動に差異がある場合もありますので、ご了承ください。

Beehaveとは

Beehaveは、Godotエンジン向けのBehaviour Treeプラグインです。

github.com

ドキュメントもしっかり完備されており、それぞれのパーツの扱い方が記載されています。本記事より詳細な説明を見たい方は英語にはなりますがこちらを参照してください。

bitbra.in

Behaviour Treeとは

端的に説明すると、AIのアルゴリズム手法のひとつで、ゲーム分野でのAIの行動決定に用いられる仕組みです。ツリー構造で制御する仕組みであり、それらをゲームエディタ上でGUIベースで構築する仕組みなどを用意することで、シンプルに動作を管理しやすく、柔軟に拡張できます。

本記事では詳細には説明しません。解説されている方の記事はあるので、そちらを参照してください。 engineering.linecorp.com

Beehaveの説明をする際にもBehaviour Treeの概念に則った説明となるため、都度確認することを推奨します。

Beehaveの導入

Beehaveはプラグインとして公開されており、一般的なプラグインの導入手順で使うことが可能です。

  1. プラグインの取得:GitHubからリリースされているBeehaveをダウンロード。
  2. プロジェクトへの追加:ダウンロードしたファイルを解凍し、addons/beehaveをそのままプロジェクトのaddonsディレクトリに配置。
  3. プラグインの有効化:Godotエディタのプロジェクト設定プラグイン タブから、Beehaveプラグインを有効化。
  4. スクリプトテンプレートの追加 : script_templatesをそのままプロジェクトのscript_templatesディレクトリに配置。

基本的な構成

Beehaveを活用したBehaviourTreeでは、ノードの階層自体がBehaviour Treeのツリーとなり、上から深さ優先探索で実行処理が行われます。 ノードには以下のような種類が存在しています。


1. Composite Node

数の子ノードを順番や条件で評価するノードになります。ツリー構造としてはそれぞれの行動や条件群の上につけるものです。
AIの流れや分岐を構成する役割となります。

主なノード 説明
Sequence 子ノードを順に実行。すべてのノードの実行を完了し完了。
Selector 子ノードを順に実行。いずれかのノードの実行を完了したら完了。(つまりひとつを選ぶ形)
RandomSelector 子ノードをランダムに選んで実行し完了。

2. Leaf Node

実際の行動や条件チェックを担当するノードです。ツリー構造の末端に配置されます。

主なノード 説明
ActionLeaf 特定の処理を実行するノード(移動、攻撃、エモートなど)
ConditionLeaf 条件を返すノード(HPが少ないか?敵が近いか?など)

主なAIの思考やそれに伴う行動の定義をここのAction LeafやCondition Leafとして実装するイメージです。実装する際には継承して実装します。


3. Decorator Node

子ノードの実行結果に変化や条件付けを与えるノードです。
たとえば子ノードの処理を繰り返したり、結果を反転して伝搬するといったロジックが可能です。

主なノード 説明
Inverter 子ノードの結果を逆転(成功 → 失敗、失敗 → 成功)
Repeater 子ノードを複数回繰り返す(無限ループや指定回数)
AlwaysSucceeder 子ノードの結果を常に成功にする(リセット用途など)

以上のノードの説明をもとに、サンプルの構成を示します。

このツリーが上から順に実行され、AIの行動となる形です。このツリーの実行結果は以下の通りになります。

  1. 準備行動を実行
  2. 攻撃条件を満たしていたら攻撃行動を実行
  3. 攻撃条件を満たしておらず、防御条件をみたしていたら防御行動を実行
  4. 1に戻ってループ

ちなみに、各所で「成功」「失敗」という書き方がありますが、これは具体的なツリーの処理に基づくものです。Beehave Treeのノード群は具体的な処理として、特定の時間経過とともにtickという関数を処理して成功と失敗を返すようになっています。

## Executes this node and returns a status code.
## This method must be overwritten.
func tick(actor: Node, blackboard: Blackboard) -> int:
    return SUCCESS

これを上から順に実行して、一連の処理となります。

  1. 一定間隔で BeehaveTree の tick() が呼ばれる。
  2. ルートノードが tick() を呼ぶ。
  3. 子ノードの tick() を再帰的に呼び出す。
  4. 各ノードは SUCCESS / FAILURE / RUNNING を返す。
  5. 返された結果に応じて上位ノードが継続・中断・失敗を判断する。

Action LeafやCondition Leafを実装する際はこの関数をoverrideしていく形です。

Blackboard

Behaviour Treeでは、各ノードが直接お互いに情報をやり取りしない設計になっています。
その代わりに使われるのがBlackboardという存在です。

これは、ノード間で値を読み書きするための共通のメモ領域のようなもので、AIの「状態」や「変数」の保管場所として機能します。

  • Condition ノードで「敵が見つかったか?」を判定したい。
  • Action ノードで「移動先の座標」や「ターゲット」を取得して行動したい。
  • 複数のノード間で「フラグ」や「ステータス」を共有したい。

Beehaveでは、BlackboardはBeehaveTreeが管理しており、前述したtick関数の引数として取り扱うことができます。

func tick(actor: Node, blackboard: Blackboard) -> int:
  # 値の取得
  var target_position = blackboard.get_value("target_pos")

  # 値の設定
  blackboard.set_value("alert", true)

Beehave Debugger

実行中のBehaviour Treeの挙動を確認するために、専用のデバッガーが用意されています。

Behaviour Tree実行時の評価フローの流れがリアルタイムで確認できるため、かなり便利です。 GUIでのサポートでこれがしっかり存在していたのが筆者としては大きな魅力でした。

まとめ

Beehaveプラグインを使用することで、GodotエンジンでのBehaviour TreeによるAI実装が大幅に効率化されます。 筆者は自作しようかなと思っていたのですが、かなり完成度の高いこちらのBeehaveを見つけて助けられました。
ぜひプロジェクトに取り入れて、何かしらのゲームAIの実装に役立ててみてください。