mcpField
L
limboai

limboai

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

limboai について

LimboAIは、AIのビヘイビアツリーや階層型ステートマシンを構築するGodot向けアドオンです。ビジュアル編集、ブラックボード、カスタムタスクを備え、BTStateで2つの制御方式を連携できます。

主な機能

  1. 01ビヘイビアツリーの実行とデバッグ
  2. 02階層型ステートマシンの管理
  3. 03ツリーと状態をつなぐBTState
  4. 04ブラックボード変数とプラン
  5. 05カスタムタスクと条件
  6. 06GDScriptとC++に対応

活用シーン

  1. 01ゲームキャラクターの行動ツリー構築
  2. 02ビヘイビアツリーと階層状態の連携
  3. 03ブラックボードによるエージェント状態の共有
  4. 04AI行動向けカスタムタスクの作成

インストール

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

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

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

同梱ファイルreferences/hsm.md

詳細

LimboAI

関連スキル: タスクが駆動する移動には ai-navigation、アドオンが不要な場合のコアエンジン FSM には state-machine、AI のアプローチ選びには godot-brainstorming を参照してください。

アドオン: LimboAI · バージョン v1.8.0 · Godot 4.6+(GDExtension)· MIT · ソース:https://github.com/limbonaut/limboai · C++ で記述(GDExtension。エンジンモジュールビルドも利用できます)。GDExtension では GDScript を使用できます。C# にはモジュールビルドが必要です(v1.8.0 では GDExtension に対応していません)。また、v1.8.0 のモジュールビルドは Godot 4.7 を対象としています。


1. LimboAI を使う場面

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

洗練されたビジュアルデバッガーを備えたビヘイビアツリーが必要な場合、階層型ステートマシンと組み合わせたい場合(BTState が両者を橋渡しします)、または C++ によるタスク実行速度が必要な場合は、LimboAI を選んでください。注意:LimboAI v1.8.0 には Godot 4.6+ が必要です。Godot 4.3 では、対応するバージョン系列は 1.2.0~1.3.x ですが、このスキルではその API を扱いません。よりシンプルな GDScript 専用のビヘイビアツリーには、より軽量な代替手段として Beehave があります。BT を使わない通常のステートマシンには、代わりに組み込みの state-machine スキルを使用してください。


2. インストールとセットアップ

GDExtension(推奨 — カスタムエンジン不要)
  1. Godot AssetLib → 「LimboAI」を検索 → ダウンロード → プロジェクトを再読み込みします。
    または GitHub Releases からダウンロードし、addons/limboai/ を res://addons/limboai/ に配置します。
  2. プラグインの切り替えは不要です。plugin.cfg はありません。プロジェクトの再読み込み後、拡張機能がエディタープラグインを自動登録します。
  3. .gdextension マニフェストは res://addons/limboai/bin/ に含まれています。
[configuration]
entry_symbol = "limboai_init"
compatibility_minimum = "4.2"

[libraries]
windows.debug.x86_64   = "res://addons/limboai/bin/liblimboai.windows.editor.x86_64.dll"
windows.release.x86_64 = "res://addons/limboai/bin/liblimboai.windows.template_release.x86_64.dll"
linux.debug.x86_64     = "res://addons/limboai/bin/liblimboai.linux.editor.x86_64.so"
linux.release.x86_64   = "res://addons/limboai/bin/liblimboai.linux.template_release.x86_64.so"
macos.debug            = "res://addons/limboai/bin/liblimboai.macos.editor.framework"
macos.release          = "res://addons/limboai/bin/liblimboai.macos.template_release.framework"
# ... (additional platform entries for linux arm64/rv64, android, iOS, web)

GDExtension の制限: LimboAI のタスクパレットにはドキュメントのツールチップが表示されません(v1.8.0 ではモジュールのみ対応)。BBParam プロパティエディターは 2025 年に GDExtension に移植されましたが、ドキュメントにはまだ未対応と記載されています。C# にはモジュールビルドが必要です(下記参照)。

モジュール版(C# または完全なエディター統合)

GitHub Releases から、コンパイル済みのエディターとエクスポートテンプレートをダウンロードします。エクスポートにはカスタムエンジンが必要です。v1.8.0 のモジュールビルドは Godot 4.7 をベースにしています(GDExtension は 4.6+ に対応)。モジュールビルドには C# 用の NuGet パッケージが含まれています。

# Add local NuGet source to your project:
# dotnet nuget add source path/to/nupkgs --name LimboNugetSource

3. ビヘイビアツリー

BehaviorTree リソースにタスクツリーを格納します。BTPlayer は各物理フレーム(またはアイドル時/手動)にツリーを実行します。BTPlayer をエージェントノードの子として追加し、BehaviorTree リソースを割り当ててください。

GDScript
# EnemyAI.gd — assign behavior_tree in the Inspector or here
extends CharacterBody2D

@onready var bt_player: BTPlayer = $BTPlayer

func _ready() -> void:
    # BTPlayer starts executing automatically (active = true by default).
    # updated(status) fires after every tree update, not only when it finishes.
    bt_player.updated.connect(_on_bt_updated)

func _on_bt_updated(status: int) -> void:
    if status == BT.SUCCESS:
        # A finished tree starts over on the next update by itself; stop it instead.
        bt_player.active = false
C#
// EnemyAI.cs
using Godot;

public partial class EnemyAI : CharacterBody2D
{
    [Export] private BTPlayer _btPlayer;

    public override void _Ready()
    {
        _btPlayer.Updated += OnBtUpdated;
    }

    private void OnBtUpdated(long status) // int signal args are long in C#
    {
        if (status == (long)BT.Status.Success)
            _btPlayer.Active = false; // a finished tree starts over on its own
    }
}

BTPlayer.UpdateMode はツリーを更新するタイミングを制御します。IDLE(毎回の _process)、PHYSICS(毎回の _physics_process。デフォルト)、または MANUAL(自分で bt_player.update(delta) を呼び出します)。


4. カスタムタスク

複数フレームにわたる処理には BTAction を、即時チェックには BTCondition を継承します。エディターで _generate_name() と _get_configuration_warnings() が機能するように、@tool を付けてください。スクリプトは res://ai/tasks/ 以下に配置します。サブフォルダーはタスクカテゴリーになります。

GDScript
@tool
extends BTAction
## Moves the agent toward a blackboard position each tick.

@export var target_pos_var: StringName = &"target_pos"
@export var speed: float = 200.0

func _generate_name() -> String:
    return "MoveToward %s" % LimboUtility.decorate_var(target_pos_var)

func _setup() -> void:
    pass  # one-time init; agent and blackboard are available here

func _enter() -> void:
    pass  # called when task transitions from non-RUNNING → RUNNING

func _tick(delta: float) -> Status:
    var target: Vector2 = blackboard.get_var(target_pos_var, Vector2.ZERO)
    if agent.global_position.distance_to(target) < 5.0:
        return SUCCESS
    agent.velocity = agent.global_position.direction_to(target) * speed
    agent.move_and_slide()
    return RUNNING

func _exit() -> void:
    pass  # cleanup after SUCCESS or FAILURE
@tool
extends BTCondition
## Returns SUCCESS if the agent is within range of a target node.

@export var target_var: StringName = &"target"
@export var distance_max: float = 150.0

var _max_sq: float

func _setup() -> void:
    _max_sq = distance_max * distance_max

func _tick(_delta: float) -> Status:
    var target = blackboard.get_var(target_var, null)  # untyped: see §5
    if not is_instance_valid(target):
        return FAILURE
    var in_range: bool = agent.global_position.distance_squared_to(
        target.global_position) <= _max_sq
    return SUCCESS if in_range else FAILURE
C#
// MoveTowardTask.cs — place in res://ai/tasks/
using Godot;

[Tool]
public partial class MoveTowardTask : BTAction
{
    [Export] public StringName TargetPosVar { get; set; } = "target_pos";
    [Export] public float Speed { get; set; } = 200f;

    public override string _GenerateName() =>
        $"MoveToward {LimboUtility.DecorateVar(TargetPosVar)}";

    public override void _Setup() { }

    public override void _Enter() { }

    public override Status _Tick(double delta)
    {
        var target = (Vector2)Blackboard.GetVar(TargetPosVar, Vector2.Zero);
        var body = (CharacterBody2D)Agent;
        if (body.GlobalPosition.DistanceTo(target) < 5f)
            return Status.Success;
        body.Velocity = body.GlobalPosition.DirectionTo(target) * Speed;
        body.MoveAndSlide();
        return Status.Running;
    }

    public override void _Exit() { }
}
// InRangeCondition.cs
using Godot;

[Tool]
public partial class InRangeCondition : BTCondition
{
    [Export] public StringName TargetVar { get; set; } = "target";
    [Export] public float DistanceMax { get; set; } = 150f;

    private float _maxSq;

    public override void _Setup() => _maxSq = DistanceMax * DistanceMax;

    public override Status _Tick(double delta)
    {
        var target = Blackboard.GetVar(TargetVar, default(Variant)).As<Node2D>();
        if (!GodotObject.IsInstanceValid(target))
            return Status.Failure;
        var agent2D = (Node2D)Agent;
        bool inRange = agent2D.GlobalPosition.DistanceSquaredTo(
            target.GlobalPosition) <= _maxSq;
        return inRange ? Status.Success : Status.Failure;
    }
}

タスクのライフサイクル:最初のティック前に _setup() を 1 回実行 → ステータスが RUNNING 以外から遷移したときに _enter() を実行 → 実行ごとに _tick(delta) を実行 → SUCCESS または FAILURE の後に _exit() を実行します。


5. ブラックボード

Blackboard は、ツリー内のすべてのタスクで共有される RefCounted のキー/値ストアです。StringName キー(&"key")を使用し、タスクのプロパティとしてエクスポートすると、インスペクターに選択欄が表示されます。

GDScript
@tool
extends BTAction

@export var speed_var: StringName = &"speed"
@export var target_var: StringName = &"target"

func _tick(delta: float) -> Status:
    # Read with a default; use no type annotation for object vars
    # to avoid errors if the stored instance was freed.
    var speed: float = blackboard.get_var(speed_var, 100.0)
    var obj = blackboard.get_var(target_var, null)
    if not is_instance_valid(obj):
        return FAILURE

    # Write back
    blackboard.set_var(speed_var, speed * 1.1)
    return RUNNING
C#
// C# has no generic GetVar<T> — cast the returned Variant.
using Godot;

[Tool]
public partial class SampleTask : BTAction
{
    [Export] public StringName SpeedVar { get; set; } = "speed";
    [Export] public StringName TargetVar { get; set; } = "target";

    public override Status _Tick(double delta)
    {
        float speed = (float)Blackboard.GetVar(SpeedVar, 100f);
        var obj = Blackboard.GetVar(TargetVar, default(Variant)).As<GodotObject>();
        if (!GodotObject.IsInstanceValid(obj))
            return Status.Failure;

        Blackboard.SetVar(SpeedVar, speed * 1.1f);
        return Status.Running;
    }
}

便利な Blackboard メソッド:has_var(name)、erase_var(name)、list_vars()、get_vars_as_dict()、bind_var_to_property(name, obj, prop)、link_var(name, target_bb, target_name)、print_state()(デバッグ用)。

BlackboardPlan は変数スキーマ(型、デフォルト値、ヒント)を定義します。BTPlayer または LimboHSM のインスペクターで編集します。blackboard_plan.create_blackboard(scene_root) を呼び出すと、実行時にスコープ付きの Blackboard が作成されます。


6. 階層型ステートマシン(LimboHSM)

LimboHSM は、子の LimboState ノードを管理する LimboState ノードです。ステートが dispatch(event) を呼び出すと、遷移が実行されます。高度なパターン(任意ステートからの遷移、BTState、ネストされた HSM、ガード条件)については、references/hsm.md を参照してください。

GDScript — シーンツリーのセットアップ
# Character.gd — scene tree: Character → LimboHSM → IdleState, MoveState
extends CharacterBody2D

@onready var hsm: LimboHSM = $LimboHSM
@onready var idle: LimboState = $LimboHSM/IdleState
@onready var move: LimboState = $LimboHSM/MoveState

func _ready() -> void:
    hsm.add_transition(idle, move, idle.EVENT_FINISHED)
    hsm.add_transition(move, idle, move.EVENT_FINISHED)
    hsm.initialize(self)
    hsm.set_active(true)
C# — シーンツリーのセットアップ
// Character.cs
using Godot;

public partial class Character : CharacterBody2D
{
    [Export] private LimboHsm _hsm; // C# name of LimboHSM
    [Export] private LimboState _idle;
    [Export] private LimboState _move;

    public override void _Ready()
    {
        _hsm.AddTransition(_idle, _move, _idle.EVENTFINISHED);
        _hsm.AddTransition(_move, _idle, _move.EVENTFINISHED);
        _hsm.Initialize(this);
        _hsm.SetActive(true);
    }
}
GDScript — ステートスクリプト
# IdleState.gd
extends LimboState

func _setup() -> void:
    pass  # agent and blackboard available; runs once during hsm.initialize()

func _enter() -> void:
    agent.get_node("AnimationPlayer").play("idle")

func _exit() -> void:
    pass

func _update(delta: float) -> void:
    if Input.get_vector(&"ui_left", &"ui_right", &"ui_up", &"ui_down").length() > 0.1:
        dispatch(EVENT_FINISHED)
C# — ステートスクリプト
// IdleState.cs
using Godot;

public partial class IdleState : LimboState
{
    public override void _Setup() { }

    public override void _Enter()
    {
        Agent.GetNode<AnimationPlayer>("AnimationPlayer").Play("idle");
    }

    public override void _Exit() { }

    public override void _Update(double delta)
    {
        if (Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down").Length() > 0.1f)
            Dispatch(EVENTFINISHED);
    }
}

実装チェックリスト

  • BTPlayer をエージェントの子として追加し、behavior_tree リソースを割り当てる
  • エディターに表示するカスタムタスクには、@tool(GDScript)または [Tool](C#)のアノテーションを付ける
  • すべての _tick は SUCCESS、FAILURE、または RUNNING を返す。void/null は返さない
  • ブラックボードのキーは、エクスポートされた StringName プロパティとして文書化する(接尾辞は _var)
  • C# でブラックボードを読み取る際は、Variant を明示的にキャストする((float)Blackboard.GetVar(...))
  • C# のサポートには、C# を使用する場合はモジュールビルドを使用する(GDExtension は使用しない)
  • 非推奨の behavior_tree_finished ではなく、BTPlayer.updated シグナルを使用する
  • HSM:すべての LimboState ノードについて、initialize() の前に add_transition で接続する
  • HSM:initialize() の後に set_active(true) を呼び出す
  • HSM の遷移に漏れがないことを確認する。到達可能なすべてのステートに終了経路がある

コメント