BehaviorTree 0.0.5
dotnet add package BehaviorTree --version 0.0.5
NuGet\Install-Package BehaviorTree -Version 0.0.5
<PackageReference Include="BehaviorTree" Version="0.0.5" />
<PackageVersion Include="BehaviorTree" Version="0.0.5" />
<PackageReference Include="BehaviorTree" />
paket add BehaviorTree --version 0.0.5
#r "nuget: BehaviorTree, 0.0.5"
#:package BehaviorTree@0.0.5
#addin nuget:?package=BehaviorTree&version=0.0.5
#tool nuget:?package=BehaviorTree&version=0.0.5
BehaviorTree
C# behavior tree library with a fluent API. Build AI and game logic as composable trees of actions and control nodes, then tick them each frame with elapsed time.
Fork and continuation of fluent-behaviour-tree by Code Capers. For background, see Fluent behavior trees for AI and game logic.
Features
- Fluent
BehaviorTreeBuilderfor readable tree construction - Composite nodes: Sequence, Selector, Parallel, Inverter
- Leaf Action nodes and boolean Condition sugar
- Splice reusable sub-trees into a parent tree
TimeDatapassed on every tick for delta-time aware logic- Async actions via
TaskandValueTaskon supported target frameworks - Full XML documentation shipped with the NuGet package
- Multi-target: .NET Framework 3.5 through .NET 10, plus
netstandard2.0/netstandard2.1
Installation
NuGet (Package Manager Console):
Install-Package BehaviorTree
.NET CLI:
dotnet add package BehaviorTree
From source: clone this repository and reference src/BehaviorTree.csproj, or build the solution under src/.
Quick start
A tree is built with BehaviorTreeBuilder and returned from Build(). The root must be a composite node (not a bare Do).
using BehaviorTree;
IBehaviorTreeNode tree;
public void Startup()
{
tree = new BehaviorTreeBuilder()
.Sequence("my-sequence")
.Do("action1", t =>
{
// Action 1.
return BehaviorTreeStatus.Success;
})
.Do("action2", t =>
{
// Action 2.
return BehaviorTreeStatus.Success;
})
.End()
.Build();
}
Tick the tree on each update of your game loop:
public void Update(float deltaTime)
{
tree.Tick(new TimeData(deltaTime));
}
TimeData exposes DeltaTime (seconds since last tick).
Behavior tree status
Nodes return one of:
| Status | Meaning |
|---|---|
Success |
The node finished and succeeded. |
Failure |
The node finished and failed. |
Running |
The node is still in progress; the tree will resume here on the next tick. |
Node types
Action (leaf)
Use Do for synchronous leaf actions. Query entities or the world, then return a status.
.Do("do-something", t =>
{
// ... do something ...
return BehaviorTreeStatus.Success;
})
Do must be nested inside a parent composite node.
Sequence
Runs children in order. Fails on the first child that returns Failure. Advances when the current child returns Success. Stays on the current child while it returns Running. Succeeds when all children succeed.
.Sequence("my-sequence")
.Do("action1", t => BehaviorTreeStatus.Success)
.Do("action2", t => BehaviorTreeStatus.Success)
.End()
Parallel
Runs all children each tick. Terminates when enough children have failed or succeeded (thresholds are configurable).
int numRequiredToFail = 2;
int numRequiredToSucceed = 2;
.Parallel("my-parallel", numRequiredToFail, numRequiredToSucceed)
.Do("action1", t => BehaviorTreeStatus.Running)
.Do("action2", t => BehaviorTreeStatus.Running)
.End()
Selector
Runs children in order until one succeeds. Fails if every child fails. Stays on a child while it returns Running.
.Selector("my-selector")
.Do("action1", t => BehaviorTreeStatus.Failure) // try next
.Do("action2", t => BehaviorTreeStatus.Success) // stop here
.Do("action3", t => BehaviorTreeStatus.Success) // not reached
.End()
Condition
Syntactic sugar over Do: a bool is mapped to Success or Failure. Often used with Selector.
.Selector("my-selector")
.Condition("condition1", t => SomeBooleanCondition())
.Do("action1", t => SomeAction())
.End()
Inverter
Inverts Success / Failure of its single child. Keeps Running while the child is Running.
.Inverter("inverter1")
.Do("action1", t => BehaviorTreeStatus.Success) // becomes Failure
.End()
.Inverter("inverter2")
.Do("action1", t => BehaviorTreeStatus.Failure) // becomes Success
.End()
Inverter accepts only one child.
Async actions
On supported target frameworks, leaf actions can return Task<BehaviorTreeStatus> or ValueTask<BehaviorTreeStatus>. The action is invoked once; the node stays Running until the task completes.
Use TickAsync to drive the tree asynchronously:
public async Task UpdateAsync(float deltaTime)
{
var status = await tree.TickAsync(new TimeData(deltaTime));
}
Task-based actions (Do overload, Condition with Task<bool>):
await new BehaviorTreeBuilder()
.Sequence("async-sequence")
.Do("fetch-data", async t =>
{
await LoadDataAsync();
return BehaviorTreeStatus.Success;
})
.Condition("has-target", async t => await HasTargetAsync())
.End()
.Build()
.TickAsync(new TimeData(deltaTime));
ValueTask-based actions (DoValue, Condition with ValueTask<bool> — netstandard2.1+ and .NET 5+ only):
.DoValue("fast-path", t => new ValueTask<BehaviorTreeStatus>(BehaviorTreeStatus.Success))
Synchronous Tick() also works on async nodes (it blocks until a pending task completes), but prefer TickAsync() in async code.
API availability by target framework
| API | Available on |
|---|---|
Tick, synchronous Do / Condition |
All targets (net35 … net10, netstandard2.0/2.1) |
TickAsync, Do with Task, Condition with Task<bool> |
net452+, netstandard2.0+, .NET 5+ |
DoValue, Condition with ValueTask<bool> |
netstandard2.1+, .NET 5+ |
Nesting
Trees can nest to any depth:
.Selector("parent")
.Sequence("child-1")
.Parallel("grand-child", 1, 1)
.Do("leaf", t => BehaviorTreeStatus.Success)
.End()
.End()
.Sequence("child-2")
.Do("leaf", t => BehaviorTreeStatus.Success)
.End()
.End()
Splicing sub-trees
Build reusable pieces separately and attach them with Splice:
private static IBehaviorTreeNode CreateSubTree()
{
return new BehaviorTreeBuilder()
.Sequence("my-sub-tree")
.Do("action1", t => BehaviorTreeStatus.Success)
.Do("action2", t => BehaviorTreeStatus.Success)
.End()
.Build();
}
public void Startup()
{
tree = new BehaviorTreeBuilder()
.Sequence("my-parent-sequence")
.Splice(CreateSubTree())
.Splice(CreateSubTree())
.End()
.Build();
}
Building and tests
From the repository root:
dotnet build src/BehaviorTree.csproj
dotnet test tests/BehaviorTree.Tests.csproj
Learn more
- Behavior tree (Wikipedia)
- Behavior trees for AI: How they work
- Understanding Behaviour Trees
- Introduction and implementation of Behaviour Trees
License
MIT — see LICENSE. Copyright © 2015 Code Capers; copyright © 2015–2026 ema.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net35 is compatible. net40 is compatible. net403 was computed. net45 was computed. net451 was computed. net452 is compatible. net46 was computed. net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 is compatible. net481 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 3.5
- No dependencies.
-
.NETFramework 4.0
- No dependencies.
-
.NETFramework 4.5.2
- No dependencies.
-
.NETFramework 4.6.2
- No dependencies.
-
.NETFramework 4.7.2
- No dependencies.
-
.NETFramework 4.8
- No dependencies.
-
.NETFramework 4.8.1
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
-
.NETStandard 2.1
- No dependencies.
-
net10.0
- No dependencies.
-
net5.0
- No dependencies.
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on BehaviorTree:
| Package | Downloads |
|---|---|
|
AOSharp.BTBot
BehaviorTree template for AOSharp bots |
GitHub repositories
This package is not used by any popular GitHub repositories.