Home

Awesome

UniBT

License: MIT GitHub release Github all releases

Free Behavior Tree designer for Unity.

Motivation

I know some designers like Behavior Designer or Arbor3.
They have many features but not for free. I will provide easily customizable and free designer.

Supported version

Features

<img src="images/demo.jpg" />

Get Started

  1. Download and install unity package.
    Also the package can also be imported with Package Manager, by adding the following entry in your Packages/manifest.json:
{
  "dependencies": {
    ...
    "com.github.yoshidan.unibt": "https://github.com/yoshidan/UniBT.git?path=Assets/UniBT/Scripts"
  }
}
  1. Add UniBT.BehaviorTree component for any GameObject.
    <img src="images/started1.jpg" width="240"/>

  2. Open Graph Editor button opens GraphView for Behavior Tree.
    <img src="images/started2.jpg" width="360"/>

  3. Add behaviors and set parameters.

  4. Finally press save button on tool bar of the editor window. (If invalid node found the color of the node become red.)
    <img src="images/started3.gif" width="480"/>

  5. Run the unity application. you can see node status in the editor window.
    <img src="images/started4.jpg" width="480"/>

    • The red node means that last Update returned Status.Failure`.
    • The green node means that last Update returned Status.Success.
    • The yellow node means that last Update returned Status.Running.
  6. you can save the GameObject with UniBT.BehaviorTree as prefab.

How It Works

Core Behavior Node

NameDescription
Composite NodeIt has one or more child nodes and controls which child node to update.
Action NodeThis is the leaf node. It execute action such as follow player, attack, escape or others you define.
Conditional NodeIt has one child node and check the condition whether child is updatable. when having no child, Conditional Node is the leaf node like Action Node.

Conditional Node has following parameter.

NameDescription
dontReEvaluateOnRunningtrue: don't re evaluate the condition if the previous status is Status.Running.

Built In Composite Node

I have prepared several built in Composite Node.

Sequence

Sequence has following parameter.

NameDescription
abortOnConditionChangedtrue: Aborts the running node when a node with a higher priority than the running node becomes infeasible. Specifically, the execution result of Conditional.CanUpdate, which is a descendant of a node with a higher priority than the running node, is used.

Selector

Selector has following parameter.

NameDescription
abortOnConditionChangedtrue: Aborts the running node when a node with a higher priority than the running node becomes executable. Specifically, the execution result of Conditional.CanUpdate, which is a descendant of a node with a higher priority than the running node, is used.

All

Random

Rotator

Rotator has following parameter.

NameDescription
resetOnAbortIt is a flag whether to return the next execution target node from the top when the execution condition of the ancestor Conditional Node changes and the running node is interrupted.

Demo Scene

Create Behaviors

Create Action

public class Wait : Action
{
    [SerializeField] 
    private float waitTime;

    private float elapsedTime = 0.0f;

    protected override Status OnUpdate()
    {
        elapsedTime += Time.deltaTime;
        if (elapsedTime < waitTime)
        {
            return Status.Running;
        }

        elapsedTime = 0.0f;
        return Status.Success;
    }

    // abort when the parent conditional changed on previous status is running.
    public override void Abort()
    { 
        elapsedTime = 0.0f;
    }
}

Create Conditional

public class IsHateGt: Conditional
{
    [SerializeField] 
    private int threshold;

    private Enemy enemy;

    protected override void OnAwake()
    {
        enemy = gameObject.GetComponent<Enemy>();
    }

    protected override bool IsUpdatable()
    {
        return enemy.Hate > threshold;
    }
}

Create Composite

public class Random : Composite
{
    private NodeBehavior runningNode;

    protected override Status OnUpdate()
    {
        // proceed to update same node when the previous status is running
        if (runningNode != null)
        {
            return HandleStatus(runningNode.Update(), runningNode);
        }

        // update random children
        var result = UnityEngine.Random.Range(0, Children.Count);
        var target = Children[result];
        return HandleStatus(target.Update(), target);
    }

    private Status HandleStatus(Status status, NodeBehavior updated)
    {
        //save running node for next update.
        runningNode = status == Status.Running ? updated : null;
        return status;
    }

    // abort when the parent conditional changed on previous status is running.
    public override void Abort()
    {
        if (runningNode != null)
        {
            runningNode.Abort();
            runningNode = null;
        }
    }
}