/BehaviourTree

Primary LanguageC#MIT LicenseMIT

BehaviourTree

Build status

Installation

// Main package
Install-Package BehaviourTree

// If you want the fluent builder capabilities
Install-Package BehaviourTree.FluentBuilder

Demo

https://www.youtube.com/watch?v=OeVo2l-O0vU

IMAGE ALT TEXT HERE

Features

  • Generic context
  • Extensible
  • Fluent Builder
  • Basic node types included
  • Tree visualizer (Coming soon)

Usage (FluentBuilder)

var behaviourTree = FluentBuilder.Create<MyContext>()
    .Sequence("root")
        .Do("walk to door", WalkToDoorFunc)
        .Selector("open door sequence")
            .Do("open door", OpenDoorFunc)
            .Sequence("locked door sequence")
                .Do("unlock door", UnlockDoorFunc)
                .Do("open door", OpenDoorFunc)
            .End()
            .Do("smash door", SmashDoorFunc)
        .End()
        .Do("walk through door", WalkThroughDoorFunc)
        .Do("close door", CloseDoorFunc)
    .End()
    .Build();

Node Types

Leaves

Action

builder.Do("my-action", context => BehaviourStatus.Succeeded)

Wait

builder.Wait("my-wait", 3000) // 3 seconds

Condition

builder.Condition("my-condition", context => true)

Composites

Sequence

builder.Sequence("my-sequence")
    .Do("action1", context => BehaviourStatus.Succeeded)
    .Do("action2", context => BehaviourStatus.Succeeded)
    .Do("action3", context => BehaviourStatus.Succeeded)
    ...
.End()

Selector

builder.Selector("my-selector")
    .Do("action1", context => BehaviourStatus.Failed)
    .Do("action2", context => BehaviourStatus.Succeeded)
    .Do("action3", context => BehaviourStatus.Succeeded)
    ...
.End()

RandomSequence

builder.RandomSequence("my-random-sequence")
    .Do("action1", context => BehaviourStatus.Succeeded)
    .Do("action2", context => BehaviourStatus.Succeeded)
    .Do("action3", context => BehaviourStatus.Succeeded)
    ...
.End()

RandomSelector

builder.RandomSelector("my-random-selector")
    .Do("action1", context => BehaviourStatus.Failed)
    .Do("action2", context => BehaviourStatus.Succeeded)
    .Do("action3", context => BehaviourStatus.Succeeded)
    ...
.End()

PrioritySequence

builder.PrioritySequence("my-priority-sequence")
    .Do("action1", context => BehaviourStatus.Succeeded)
    .Do("action2", context => BehaviourStatus.Succeeded)
    .Do("action3", context => BehaviourStatus.Succeeded)
    ...
.End()

PrioritySelector

builder.PrioritySelector("my-priority-selector")
    .Do("action1", context => BehaviourStatus.Failed)
    .Do("action2", context => BehaviourStatus.Succeeded)
    .Do("action3", context => BehaviourStatus.Succeeded)
    ...
.End()

SimpleParallel

public enum SimpleParallelPolicy
{
    BothMustSucceed,
    OnlyOneMustSucceed
}

var policy = SimpleParallelPolicy.BothMustSucceed;

builder.SimpleParallel("my-parallel", policy)
    .Do("action1", context => BehaviourStatus.Running)
    .Do("action2", context => BehaviourStatus.Running)
.End()

Decorators

Cooldown

builder.Cooldown("my-cooldown", 4000) // 4 seconds
    .Do("action1", context => BehaviourStatus.Failed)
.End()

Failer

builder.AlwaysFail("my-failer")
    .Do("action1", context => BehaviourStatus.Succeeded)
.End()

Succeeder

builder.AlwaysSucceed("my-succeeder")
    .Do("action1", context => BehaviourStatus.Failed)
.End()

Inverter

builder.Invert("my-inverter")
    .Do("action1", context => BehaviourStatus.Failed)
.End()

RateLimiter (Cache)

builder.LimitCallRate("my-rate-limiter", 1000) // 1 second
    .Do("action1", context => BehaviourStatus.Failed)
.End()

Repeat

builder.Repeat("my-repeater", 5)
    .Do("action1", context => BehaviourStatus.Failed)
.End()

TimeLimit

builder.TimeLimit("my-time-limit", 5000) // has 5 seconds to complete or will fail
    .Do("action1", context => BehaviourStatus.Running)
.End()

UntilSuccess

builder.UntilSuccess("my-until-success")
    .Do("action1", context => BehaviourStatus.Failed)
.End()

UntilFailed

builder.UntilFailed("my-until-failed")
    .Do("action1", context => BehaviourStatus.Succeeded)
.End()

Random

builder.Random("my-random", 0.6) // will call child 60% of the time
    .Do("action1", context => BehaviourStatus.Succeeded)
.End()

SubTree

builder.SubTree("my-sub-tree", otherBehaviourTree)