Behavior Trees In Unity

Creating a Behavior Tree with Scriptable Objects

Source: https://thekiwicoder.com/wp-content/uploads/2021/07/behaviour_tree-2.jpg

This is a a version of the Behavior Tree Created by the KIWI Coder.

I have already talked about the Strategy, Decorator, and Composite patterns and built a simple Ability System along the way. Now I am going to look at building a Behavior Tree using UI Builder, GraphView, and Scriptable Objects in Unity 2021.3.1f1; any version of Unity 2019.1 or newer will work, 2020.1 or newer to use the UI Builder. The Graph View is what is used in Shader Graph, The Animator window, and other node based editor windows in unity.The concepts here can be used to create any node base tree view editor window. Some examples would be Behavior Trees, Custom State Machine System, or even the Ability System from my previous articles.

Behavior Tree Concept

Behavior trees are a formal, graphical modelling language used primarily in systems and software engineering. Behavior trees employ a well-defined notation to unambiguously represent the hundreds or even thousands of natural language requirements that are typically used to express the stakeholder needs for a large-scale software-integrated system.

Source: https://en.wikipedia.org/wiki/Behavior_tree

My Behavior Tree is an execution tree (uses the Strategy pattern) and always starts with a Root Node. This will be so that the behavior tree knows where to start. Root Node has only one child. Now there are 3 basic main type of nodes Decorator, Composite Node and Action Node.

Each Node can return one of three states Running, Success, or Failure.

All nodes will be saved in Unity as Scriptable Objects. A Behavior tree will be a Scriptable Object containing all the Nodes in it.

Creating the Behavior Tree

Now that I know what my behavior tree is going to look like I need to create it.

The Node

The first thing that I will need is to define what a Node is. All of the Nodes will be a Scriptable Object. The reason I am using Scriptable Objects is that I know that I am going to build an Editor to Edit the Behavior Tree, this Editor will be using UXML and Serialized Object data binding which has specific requirements. so I will make node an abstract class so I have to create sub-types of this and can’t create it directly.

Next I will define the states that the Node can be in as an ENUM.

State Enum

I will also need to keep track of whether this node has started or not.

Has the Node Started

Now I need to create the Abstract Methods that every node has to implement.

Node Abstract Methods

Now I need a way to make the Node Update and get the State that the node is in.

Pseudo Code for Update Method

The completed method looks like this.

Completed Update Method

I then inverted my running check it makes the code look cleaner in my opinion.

Invert If Statement
Abstract Node Unity Object

The Behavior Tree

Now I can create my Behavior Tree.

Create Behavior Tree

Now I need a way to create the Behavior Tree, I will use the Create asset Menu Class Attribute. I did not do this with the Nodes because the Behavior Tree Editor Window will be responsible for this.

Create Asset Menu

Now The Behavior Tree Needs the Root Node, the entry point.

Root Node

It needs a Node State to represent the entire state of the tree.

State of Tree

Now I need an Update Method that mirrors the Nodes. It should return failure if there is no root node. If the root node is running then it should update the root node, set it’s state to be the state to be the root nodes state and return the State that the tree is currently in.

Behavior Tree Update Method

Node Sub-types.

Now I need to create the 3 Node Sub-types, Decorator Node, Composite Node, and Action Node. All of these are Abstract Nodes. The Interface, Abstract members will be implemented on the individual Action Nodes that inherit from these node types.

Decorator Node — has one child and is capable of augmenting the return state of it’s child. This uses the Decorator pattern.

Decorator Node

Composite Node — has a list of children and is the control flow of the behavior tree like switch statements and for loops. There are 2 types Composite Nodes the Selector and Sequence. This uses the Composite pattern.

Composite Node

Action Node — the Leaf of the tree, has no children, and is where all of the logic gets implemented.

Action Node

Debug Log Node — Action node that logs a message.

Debug Log Action Node

Now All I need to do is have a Message to log and fill in the Methods. In the Update method I will return The State of Success since there is no way that this node can fail.

Debug Log Node completed.

Creating and running the Tree

Now I have enough created in order to create a MonoBehaviour that runs my tree.

Behavior Tree Runner

I need to keep track of the Behavior Tree that I am running.

Now I need to Update The Behavior Tree.

Behavior Tree Runner Update Method

For now I will create the tree in the Start Method. The tree needs a root Node to run so I will Create a Debug Log Node and add it to the tree as the root node. I will change this latter, I will have an Editor that for Editing Behavior Trees.

Behavior Tree Runner Start Method for Testing

In Unity I created an empty Game Object in the Scene and added the Behavior Tree Runner Component to it.

Behavior Tree Runner Game Object

Now when I run the project the Behavior Tree runs.

Make things more interesting.

Lets make this tree more interesting by adding some other node types.

Repeat Node — A Decorator Node that augments the return state of it’s child to be Running.

Repeat Node

I could do anything I want with this repeat node, add variables for the number of times to repeat, repeat until the node fails, or repeat until the child node succeeds.

I can add this to my Behavior Tree Runner in the Start Method

Behavior Tree Runner Start Method for Testing Added Repeat Node

My Tree will run forever.

Repeat Decorator Node Running

Sequencer Node — Composite Node that Runs all of the children in Sequence.

Sequencer Node

For the On Update Method, if any of the children fail then this node should fail, if all the children return success then this Node returns Success, if there are no children return Failure, if the child state is an unrecognized state return Failure.

Sequencer Node On Update

Now the fancy if statement with the switch expression is the same as :

On Update if pattern and switch expression explained

To use this new node I just added it to the Behavior Tree Start Method

Behavior Tree Runner Start Method for Testing Added Sequencer Node
Sequencer Composite Node Running

Selector Node — Composite Node that selects one of it children to run based on some condition.

Wait Node —Action Node that waits for a period of time before returning success.

Wait Action Node
Behavior Tree Runner Start Method for Testing Added Wait Node

Now when I first did this I used delta time instead of time and my wait node did not work correctly. This is the importance of testing.

What’s Next

Now that I have my behavior Tree created and working it is time to build a way to create and edit my behavior trees. As this article is longer then I expected stay tuned for Part 2 where I build an Editor to edit my behavior trees, like we can Edit the Animator Controller.

Get The Code.

As always my code is on GIT HUB.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store