mcpField
B
beehave

beehave

github.com/jame581開発889137 回インストール4 日前に更新
リポジトリ

beehave について

Beehave は GDScript 製の Godot 4.1+ 向け軽量ビヘイビアツリープラグインです。シーンツリーでゲーム AI を構成するプロジェクトに適しており、コンポジット、デコレーター、Blackboard、実行時の可視化機能を備えます。

主な機能

  1. 01シーンツリー形式のビヘイビアツリー
  2. 02コンポジットとデコレーター
  3. 03共有 Blackboard のキー・バリューストア
  4. 04実行時のビヘイビアツリー可視化
  5. 05ツリーの実行頻度調整

活用シーン

  1. 01ゲームキャラクターの AI 行動を構成
  2. 02攻撃条件と巡回アクションを組み合わせ
  3. 03複数のビヘイビアツリー間で状態を共有
  4. 04実行時にノードの処理状況を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jame581/godotprompter --skill beehave

インストール後、Claude Code で/beehaveを入力して読み込まれたか確認します。

同梱ファイルreferences/custom-nodes.md

詳細

Beehave

関連スキル: 移動のリーフには ai-navigation、コアエンジンの FSM には state-machine、より高機能な C++ BT+HSM の代替手段には limboai、AI アプローチの選択には godot-brainstorming を使用します。

アドオン: Beehave · バージョン v2.9.2 · Godot 4.1+ · MIT · ソース:https://github.com/bitbrain/beehave · GDScript で記述(公式の C# API はありません。このスキルは設計上 GDScript のみを対象としています)。


1. Beehave を使用する場面

アプローチ最適な用途
コアエンジンの FSM(state-machine スキル)シンプルなエージェント、状態が 5 個未満、アドオンなし
Beehave(GDScript アドオン)軽量な BT、GDScript のみのプロジェクト、迅速なイテレーション
LimboAIBT と HSM を併用、ビジュアルエディター、C++ のパフォーマンス、C# サポート(モジュールビルド)

プロジェクトが GDScript のみで、カスタムエンジンビルドなしでビヘイビアツリーを使用したい場合や、シンプルなシーンツリー内のノードを使った編集ワークフローを重視する場合は Beehave を選びます。Beehave のツリーはすべてシーンツリー内にあります。各コンポジット、デコレーター、リーフは通常の Node 子ノードです。HSM 統合を備えた、より高機能な C++/C# ソリューションには、代わりに limboai スキルを使用します。BT を使わない通常のステートマシンには、組み込みの state-machine スキルを使用します。

C# に関する注意: Beehave には公式の C# API がありません(addons/beehave/ 内の .cs ファイルは 0 個です)。C# からは Godot の言語間相互運用機能を使って GDScript API を呼び出せます(GetNode<Node>(...).Call("tick", actor, blackboard))が、Beehave は型付きの C# クラスを提供していません。


2. インストールと有効化

  1. Godot AssetLib → 「Beehave」を検索 → ダウンロード → プロジェクトを再読み込みします。
    または、GitHub release から addons/beehave/ フォルダーを res://addons/beehave/ にコピーします。
  2. プラグインを有効にします:Project → Project Settings → Plugins → Beehave にチェックを入れます。
    2 つのオートロードが登録されます:BeehaveGlobalMetrics と BeehaveGlobalDebugger。
  3. 任意 — リーフのひな形テンプレートを使う場合は、アドオンの script_templates/ をプロジェクトのルートにコピーします。

3. ツリーの構成

Beehave のツリーは、通常のシーンツリーの子ノードとして配置する、次の 3 種類のノードで構成されます。

役割ノード動作
ツリーのルートBeehaveTree毎フレーム(または物理フレーム/手動)子ノードをティックします。BeehaveNode ではなく Node を継承します
コンポジットSequenceComposite、SelectorComposite、SimpleParallelComposite、…フロー制御 — AND/OR/並列ロジック
デコレーターInverterDecorator、CooldownDecorator、RepeaterDecorator、…1 つの子ノードをラップして、その結果を変更します
リーフActionLeaf、ConditionLeaf のサブクラス独自のゲームロジック
コンポジットのクイックリファレンス
クラスロジック
SequenceCompositeAND — すべての子ノードが成功する必要があります。最初の失敗で失敗します
SequenceReactiveCompositeAND — 実行中は、毎ティック最初の子ノードから再評価します
SelectorCompositeOR — 最初に成功した時点で成功します。すべて失敗すると失敗します
SelectorReactiveCompositeOR — 実行中は、毎ティック最初の子ノードから再評価します
SimpleParallelComposite2 つの子ノードを同時に実行します。結果はプライマリ(子ノード 0)に従います
SequenceRandomCompositeシャッフルした AND — 子ノードをランダムな順序で実行します
SelectorRandomCompositeシャッフルした OR — 子ノードをランダムな順序で試します
デコレーター早見表
クラス効果
InverterDecoratorSUCCESS と FAILURE を反転し、RUNNING はそのまま通します
AlwaysSucceedDecoratorSUCCESS を強制し、RUNNING はそのまま通します
AlwaysFailDecoratorFAILURE を強制し、RUNNING はそのまま通します
RepeaterDecorator子ノードが repetitions 回成功するまで再実行します
LimiterDecorator子ノードの実行ティック数を max_count に制限し、その後 FAILURE を返します
CooldownDecorator子ノードの終了後、wait_time 秒間は再実行をブロックします
TimeLimiterDecorator子ノードに wait_time 秒を与え、まだ実行中の場合は中断します
DelayDecorator子ノードの初回実行前に wait_time 秒待機します
UntilFailDecorator子ノードが FAILURE を返すまでループし、その後 SUCCESS を返します
最小限のシーンツリーの例
# Scene tree:
#   Enemy (CharacterBody2D)
#     BeehaveTree               ← tick_rate = 1, process_thread = PHYSICS
#       SelectorComposite
#         SequenceComposite     ← "attack if in range"
#           IsInRangeCondition
#           AttackAction
#         PatrolAction          ← fallback

# BeehaveTree exports:
# @export var enabled: bool = true
# @export var tick_rate: int = 1          (1 = every frame; 3 = every 3 frames)
# @export var process_thread: ProcessThread = PHYSICS
# @export var blackboard: Blackboard      (auto-created if not set)
# @export_node_path var actor_node_path   (defaults to parent node)

# Access the tree from code if you need manual control:
@onready var bt: BeehaveTree = $BeehaveTree

func _ready() -> void:
    # Reduce tick cost: evaluate AI every 3 physics frames
    bt.tick_rate = 3
    # Default process_thread is PHYSICS — switch to IDLE if actor uses _process
    bt.process_thread = BeehaveTree.ProcessThread.IDLE

tick_rate に関する注意: tick_rate = 1 は毎フレーム評価し、tick_rate = 3 は3フレームごとに評価します。CPU 使用量を抑えるには、遠くにいる NPC やバックグラウンドの NPC では値を大きくしてください。デフォルトのプロセススレッドは PHYSICS です。アクタースクリプトが _physics_process ではなく _process を使用する場合は、同期を保つために process_thread = IDLE を設定してください。


4. リーフの仕様

リーフにはゲームロジックを記述します。複数ティックにわたる処理には ActionLeaf を、単一フレームのチェックには ConditionLeaf をサブクラス化し、tick(actor, blackboard) をオーバーライドしてください。

# IsInRangeCondition.gd
class_name IsInRangeCondition
extends ConditionLeaf

@export var detection_range: float = 150.0

func tick(actor: Node, blackboard: Blackboard) -> int:
    # Beehave types `actor` as Node; cast to your concrete type for 2D members.
    var body := actor as Node2D
    var target: Node2D = blackboard.get_value("target")
    if body == null or not is_instance_valid(target):
        return FAILURE
    var in_range := body.global_position.distance_to(target.global_position) <= detection_range
    return SUCCESS if in_range else FAILURE
# AttackAction.gd
class_name AttackAction
extends ActionLeaf

@export var attack_duration: float = 0.5

func tick(actor: Node, blackboard: Blackboard) -> int:
    var elapsed: float = blackboard.get_value("attack_elapsed", 0.0)
    elapsed += get_physics_process_delta_time()

    if elapsed >= attack_duration:
        blackboard.erase_value("attack_elapsed")
        # `actor` is typed Node; guard game-specific methods (or cast to your actor type).
        if actor.has_method("play_attack_animation"):
            actor.call("play_attack_animation")
        return SUCCESS

    blackboard.set_value("attack_elapsed", elapsed)
    return RUNNING

func interrupt(actor: Node, blackboard: Blackboard) -> void:
    # Clean up per-run state when the tree interrupts this action (after_run is not called then)
    blackboard.erase_value("attack_elapsed")
    super(actor, blackboard)  # keeps the debugger's interrupt message

戻り値(BeehaveNode で定義):

  • SUCCESS — アクションが完了した、または条件を満たしています。
  • FAILURE — アクションが失敗した、または条件を満たしていません。次に何をするかは親コンポジットが決定します。
  • RUNNING — アクションにさらにフレームが必要です。ツリーは次のフレームに再度 tick() を呼び出します(ActionLeaf のみ。ConditionLeaf は RUNNING を返してはいけません)。

任意のオーバーライド:

  • before_run(actor, blackboard) — 実行の最初のティックの前に一度呼び出されます。
  • after_run(actor, blackboard) — SUCCESS/FAILURE を返すティックの後に呼び出されます。中断時には呼び出されません。
  • interrupt(actor, blackboard) — ツリーが実行中のノードを中断するときに呼び出されます。

5. ブラックボード

Blackboard ノードは、すべての tick() 呼び出しに渡される共有キー/値ストアです。外部の Blackboard ノードを割り当てていない場合、BeehaveTree は内部用のものを自動作成します。

# Share one Blackboard across multiple BeehaveTrees on the same actor.
# Assign the same exported Blackboard node to each tree in the Inspector.

# Read / write from any leaf's tick():
func tick(actor: Node, blackboard: Blackboard) -> int:
    # Write
    blackboard.set_value("target", actor.get_nearest_enemy())

    # Read with default
    var speed: float = blackboard.get_value("move_speed", 200.0)

    # Conditional check
    if blackboard.has_value("stunned"):
        return FAILURE

    # Erase (sets key to null; has_value returns false after erase)
    blackboard.erase_value("temp_flag")

    return SUCCESS

名前付き名前空間: set_value、get_value、has_value、erase_value は、任意の blackboard_name: String パラメーターを受け取ります(デフォルトは "default")。これを使用すると、名前の衝突を避けて、1つの Blackboard ノード上で名前空間を分けられます(例:敵ごとの状態と共有ワールド状態)。

組み込み式リーフ: BlackboardSetAction、BlackboardEraseAction、BlackboardHasCondition、BlackboardCompareCondition を使うと、Inspector のエクスポート項目だけで Blackboard を操作できます(GDScript は不要です)。式は Godot の Expression.execute([], blackboard) で実行されるため、式の文字列内で get_value("key") を直接呼び出せます。


6. ビジュアルデバッガー

Beehave には EditorDebuggerPlugin が含まれており、ゲームの実行中にエディタ下部のパネルに 🐝 Beehave タブが追加されます。

  1. Godot エディタからプロジェクトを実行します。
  2. Debugger パネルを開き、🐝 Beehave タブをクリックします。
  3. リストからツリーを選択してライブ表示を有効にします。アクティブなノードは各ティックでハイライト表示されます。
  4. 任意:切り離しボタンをクリックしてパネルをフローティング表示にするか、Project Settings → beehave/debugger/start_detached = true を設定して常に切り離された状態で起動します。

Performance パネルでツリーごとの CPU 使用コストを追跡するには、BeehaveTree ノードで custom_monitor = true を設定します。これにより、beehave [microseconds]/process_time_<actor_name>-<id> が Performance モニターとして登録されます。

カスタムデコレーターや条件の作成手順については、references/custom-nodes.md を参照してください。


実装チェックリスト

  • addons/beehave/ をプロジェクトにコピーし、プロジェクト設定 → プラグインでプラグインを有効化した
  • BeehaveTree をアクターの子として追加し、actor_node_path を設定した(または空欄のままにして親をデフォルトにした)
  • process_thread をアクターのループに合わせた:_physics_process には PHYSICS、_process には IDLE
  • tick_rate を調整した。バックグラウンドの NPC では値を増やし(例:3)、フレームごとの負荷を軽減した
  • すべての tick() オーバーライドが SUCCESS、FAILURE、または RUNNING を返すことを確認した。void や null は返さない
  • ConditionLeaf のサブクラスが RUNNING を返さないことを確認した
  • 実行ごとの状態は Blackboard に書き込み、リーフノード自体には保存しない
  • after_run または interrupt で、アクションが書き込んだ Blackboard キーをクリーンアップする
  • 複数の BeehaveTree ノードで同じデータが必要な場合は、外部の Blackboard ノードをエクスポートして共有する
  • AI ロジックをリリースする前に、実行時にビジュアルデバッガーでティックの流れを確認する

コメント