Behavior Trees in Godot with LimboAI

Updated June 2026
Behavior trees are a scalable, composable alternative to state machines for game AI, and LimboAI is the leading implementation for Godot 4.x. Built in C++ for performance with full GDScript support for custom tasks, LimboAI provides a visual editor, runtime debugger, blackboard data system, and hierarchical state machines that can work alongside behavior trees for hybrid AI architectures.

State machines work well for simple AI with a few states, but they become difficult to maintain as complexity grows. Adding a new state requires updating transition logic in every existing state that might connect to it. Behavior trees solve this by organizing decisions hierarchically, where new behaviors can be added as branches without modifying existing logic. The tree evaluates from the root each tick, and the structure itself determines priority and fallback behavior, making the AI easier to reason about, extend, and debug.

Install LimboAI

LimboAI is available through two distribution methods: as a GDExtension addon or as a compiled C++ module. The GDExtension version is easier to install and works with the standard Godot editor download. Open the Godot Asset Library from the AssetLib tab in the editor, search for "LimboAI," and install the version matching your Godot release (4.6 for the current stable). The addon files are placed in your project's addons directory and activate automatically.

The compiled module version offers slightly more features and better performance since it integrates directly into the engine binary. This requires either downloading a pre-built Godot editor with LimboAI included from the LimboAI GitHub releases page, or compiling Godot from source with LimboAI as a module. For most projects, the GDExtension version provides everything you need without the complexity of custom engine builds.

After installation, the editor gains a new BehaviorTree resource type, a visual tree editor panel, and a runtime debugger panel. Create a new BehaviorTree resource from the FileSystem dock (right-click, New Resource, BehaviorTree) and the visual editor opens in a new bottom panel where you build your tree by adding and connecting nodes.

Understand Behavior Tree Structure

A behavior tree is a directed acyclic graph of nodes that each return one of three statuses when evaluated: SUCCESS, FAILURE, or RUNNING. The tree is traversed from the root node each tick, and the status returned by child nodes determines which path the tree follows. This simple protocol is what makes behavior trees so flexible.

Composite nodes control the flow of execution through their children. A Sequence node executes its children from left to right and succeeds only if all children succeed; it fails as soon as any child fails. A Selector (also called Fallback) executes children from left to right and succeeds as soon as any child succeeds; it fails only if all children fail. A Parallel node executes all children simultaneously and succeeds or fails based on configurable thresholds.

Decorator nodes modify the behavior of a single child. Common decorators include Inverter (flips success to failure and vice versa), AlwaysSucceed (ignores the child's failure), Repeat (loops the child a set number of times), and Limiter (prevents the child from running more than once per specified interval). Decorators add nuance without requiring new task implementations.

Leaf nodes are the endpoints that actually do things. Actions (BTAction in LimboAI) perform operations like moving to a position, playing an animation, or applying damage. Conditions (BTCondition) check the world state, like whether a target is in range, whether health is above a threshold, or whether a timer has elapsed. Actions return RUNNING while in progress and SUCCESS or FAILURE when complete. Conditions return SUCCESS or FAILURE immediately.

Create Your First Behavior Tree

A practical starting tree for an enemy has a Selector as the root with three child branches: combat, investigate, and patrol. The Selector evaluates left to right, so combat takes the highest priority. If the combat branch fails (no target detected), the tree tries investigation. If investigation fails (no recent stimulus), it falls through to patrol, which always succeeds as the default behavior.

The combat branch is a Sequence with three children: a condition that checks if a target exists in the blackboard, an action that moves toward the target using the NavigationAgent, and an action that performs an attack when within range. Because this is a Sequence, all three must succeed for combat to complete. If the target check fails, the entire combat branch fails, and the Selector moves to the next branch.

The patrol branch is another Sequence: select the next waypoint from the patrol array, navigate to it, wait for a random duration, then loop. Wrapping this in a Repeat decorator with infinite repeats keeps the patrol running continuously. The patrol branch rarely fails since it does not depend on external conditions, making it a reliable fallback that keeps the enemy active when nothing else demands attention.

In the LimboAI visual editor, you build this tree by right-clicking to add nodes, dragging connections between parents and children, and configuring each node's properties in the Inspector. The visual layout makes the tree structure immediately readable, and you can rearrange branches to change priority order by simply moving nodes left or right under their parent.

Write Custom Tasks in GDScript

LimboAI provides many built-in tasks for common operations, but game-specific behaviors require custom tasks written in GDScript. Custom actions extend the BTAction class and override three methods: _setup() for initialization, _enter() called when the task starts executing, and _tick(delta) called each frame while the task is active. The _tick method returns SUCCESS, FAILURE, or RUNNING.

A custom "move to target" action might get the target position from the blackboard in _enter(), set it as the NavigationAgent's target, and in _tick() move the character toward the next path position. It returns RUNNING while the agent is navigating and SUCCESS when the agent reports navigation finished. If the target becomes invalid during navigation, it returns FAILURE, which causes the parent Sequence to fail and the tree to try alternative branches.

Custom conditions extend BTCondition and override _tick(delta) to return SUCCESS or FAILURE based on a game state check. A "is target in range" condition reads the target reference from the blackboard, calculates the distance to the agent's character, and returns SUCCESS if within the configured range or FAILURE otherwise. Conditions should be lightweight since they may be evaluated many times per second across multiple enemies.

LimboAI tasks access the agent (the AI character node) through agent property and the scene tree through standard Godot APIs. This means your custom tasks can interact with any part of the game: playing sounds, spawning effects, querying physics, or sending signals. The task system is the bridge between the abstract behavior tree logic and your concrete game implementation.

Use the Blackboard for Data Sharing

The Blackboard is a key-value store attached to each behavior tree instance that allows tasks to share data without direct references to each other. A detection system writes the target reference to the blackboard under a "target" key. A movement task reads the "target" key to get the destination. A combat task reads the same key to determine what to attack. None of these tasks know about each other; they only interact through the shared data store.

Set blackboard values with blackboard.set_var("key", value) and read them with blackboard.get_var("key") or blackboard.get_var("key", default_value) which returns a default if the key does not exist. Common blackboard entries include the current target node, the last known target position, the home position for retreating, alert level, available ammunition, and the current path.

Blackboard plans in LimboAI define the expected variables and their types, which serves as documentation and enables validation. Creating a blackboard plan for your enemy type documents what data the tree expects and what each variable means. This is especially valuable when multiple developers work on the same AI, since the plan makes the data contract explicit rather than relying on convention or documentation that might fall out of date.

The blackboard can also be shared between a behavior tree and a state machine, or between the behavior tree and external game systems. A game manager that detects a global alarm state can write to the blackboard, causing all enemies using that blackboard to respond to the alarm on their next tree tick. This makes coordinated group behavior straightforward to implement without complex inter-enemy communication code.

Debug with the Visual Debugger

LimboAI includes a runtime visual debugger that shows the behavior tree during gameplay with real-time status indicators. Each node is color-coded: green for SUCCESS, red for FAILURE, and yellow for RUNNING. The currently executing path through the tree is highlighted, making it immediately obvious which branch the AI is following and which conditions are succeeding or failing.

Enable the debugger by selecting an enemy in the running game's remote scene tree (under the Debugger panel) and opening the BT Debugger tab. The tree visualization updates every tick, showing exactly which nodes are evaluated and in what order. When an AI is behaving unexpectedly, the visual debugger almost always reveals the cause immediately, whether it is a condition checking the wrong blackboard key, a sequence failing early because of a missing check, or a task stuck in RUNNING because it never reaches its completion condition.

The debugger also shows blackboard values, so you can verify that the data flowing between tasks is what you expect. If a "move to target" task is failing because the target position in the blackboard is stale or null, you will see it right there. This combination of tree state and data state visibility makes LimboAI's debugger one of the most productive AI debugging tools available in any game engine.

Combine with Hierarchical State Machines

LimboAI provides a Hierarchical State Machine (HSM) system that integrates with behavior trees for hybrid architectures. The HSM manages high-level states like peaceful, alert, and combat, while behavior trees handle the detailed decision-making within each state. Each state in the HSM can have its own behavior tree or simple script logic.

This hybrid approach works well because some transitions are best modeled as explicit state changes (the enemy goes from peaceful to alerted when it hears a gunshot) while detailed behavior within a state benefits from the composability of behavior trees (the alert state involves searching the area, checking hiding spots, calling for backup, and gradually returning to peaceful if nothing is found).

HSM states in LimboAI extend the LimboState class and override _enter(), _exit(), and _update(delta). Transitions between states are defined as event-driven connections in the editor. The state machine dispatches events that trigger transitions, and guards (conditions) on transitions can prevent them unless certain criteria are met. This gives you precise control over when and how the AI switches between major behavioral modes.

Key Takeaway

LimboAI brings production-quality behavior trees to Godot with a visual editor, runtime debugger, blackboard data sharing, and hierarchical state machine integration, letting you build complex, maintainable AI that scales from simple enemies to sophisticated game characters.