A lightweight behaviour tree framework developed by Grove Games for .NET and Godot
$ dotnet add package GroveGames.BehaviourTree.GodotA modular and extensible behavior tree framework for AI development in C# for the .NET and Godot Engine. This system allows for the creation of complex AI behaviors by combining various Node, Composite, and Decorator components.
This behavior tree framework enables AI agents to make decisions and perform actions based on conditions in a dynamic environment. Use this setup to build intelligent game characters with modular and reusable nodes.
Selector, Sequence, Decorator, and custom action nodes.Install the package via .NET CLI:
dotnet add package GroveGames.BehaviourTree
For Godot:
dotnet add package GroveGames.BehaviourTree.Godot
To set up a behavior tree, create a class that inherits from Tree and override the SetupTree method to define the AI structure.
graph TD
Root(Root) --> Selector
Selector --> AttackSequence(Sequence: Attack Sequence)
Selector --> DefendSequence(Sequence: Defend Sequence)
AttackSequence --> Condition1[Condition: IsEnemyVisible == true]
AttackSequence --> Cooldown1[Cooldown]
Cooldown1 --> Repeater1[Repeater]
Repeater1 --> Attack[Attack]
DefendSequence --> Condition2[Condition: IsUnderAttack == true]
DefendSequence --> Cooldown2[Cooldown]
Cooldown2 --> Repeater2[Repeater]
Repeater2 --> Defend[Defend]
public class Attack : Node
{
public Attack(IParent parent) : base(parent) {}
public override NodeState Evaluate(float delta)
{
Console.WriteLine("Attacking");
return NodeState.Running;
}
}
public class Defend : Node
{
public Defend(IParent parent) : base(parent) {}
public override NodeState Evaluate(float delta)
{
Console.WriteLine("Defending");
return NodeState.Running;
}
}
Here's an example of a CharacterBT class that builds an AI behavior tree:
public class CharacterBT : Tree
{
public CharacterBT(GroveGames.BehaviourTree.Nodes.Root root) : base(root) { }
public override void SetupTree()
{
var selector = Root.Selector();
var attackSequence = selector.Sequence();
attackSequence.Attach(new Condition(() => IsEnemyVisible()));
attackSequence
.Cooldown(1f)
.Repeater(RepeatMode.UntilSuccess)
.Attach(new Attack(attackSequence));
var defendSequence = selector.Sequence()
defendSequence.Attach(new Condition(() => IsUnderAttack()));
defendSequence
.Cooldown(1f)
.Repeater(RepeatMode.UntilSuccess)
.Attach(new Defend(defendSequence));
}
}
To assist with testing and debugging behavior trees, GroveGames Behaviour Tree includes a Visual Debugger that helps track the current state of each node in real-time.
Enable Visual Debugger: To use the debugger, ensure your behavior tree class derives from GodotBehaviourTree. After instantiating your behavior tree, call the SetRoot method and pass in a new Root node to initialize the tree structure. Additionally, remember to call the Enable method to activate debugging. Here’s an example:
public override void _Ready()
{
_characterBT = new CharacterBT();
_characterBT.SetRoot(new Root(new Blackboard()));
_characterBT.SetupTree();
_characterBT.Enable();
AddChild(_characterBT);
}
Node State Tracking: Once enabled, you can observe states such as Running, Success, or Failure for each node. This is especially useful for visualizing sequences, conditions, and actions that may fail or succeed based on game conditions.
Godot Integration: With debugging enabled, information about node states will be displayed under the Debugger tab, allowing you to track the AI behavior tree’s state updates frame-by-frame.
Below is an example of how a behavior tree appears in the visual debugger, showing nodes and their states during runtime.

Below is a full example of setting up and using the behavior tree in a Godot scene:
public partial class Character : Godot.Node
{
private CharacterBT _characterBT;
public override void _Ready()
{
_characterBT = new CharacterBT(new Root(new Blackboard()));
_characterBT.SetupTree();
}
public override void _Process(double delta)
{
_characterBT.Tick((float)delta);
}
public override void _Input(InputEvent @event)
{
if (@event.IsPressed())
{
_characterBT.Abort(); // Aborts the current tree
}
}
}
Extend the framework with new functionality by creating custom nodes:
Node and implement specific behaviors in Evaluate.Decorator and modify the behavior of a single child node.Composite and define logic for multiple child nodes.This Delayer decorator delays the execution of a child node by a specified amount of time:
public class Delayer : Decorator
{
private readonly float _waitTime;
private float _interval;
public Delayer(IParent parent, float waitTime) : base(parent)
{
_waitTime = waitTime;
}
public override NodeState Evaluate(float deltaTime)
{
_interval += deltaTime;
if (_interval >= _waitTime)
{
_interval = 0f;
return base.Evaluate(deltaTime);
}
else
{
return NodeState.Running;
}
}
public override void Reset()
{
_interval = 0f;
}
}
This decorator only allows the child node to execute once the specified wait time has passed.
Contributions are welcome! To contribute:
git checkout -b feature/your-feature).git commit -am 'Add new feature').git push origin feature/your-feature).This project is licensed under the MIT License - see the LICENSE file for details.