Installing        3

Unity Versions        3

Download package        3

Optional package        3

Quick setup        4

Setup        4

Create first Graph        4

Create first behaviour        4

Editor Usage        5

Structure        5

Editor        6

Interface        6

Toolbar        6

Hierarchy        6

Inspector        6

Variables        6

Node Field        7

Debugger        7

Nodes        8

Actions/Conditions        8

Context        8

Graph Context        9

Global Context        9

Start Node        10

Task Node        10

Subgraph Node        10

Exit Node        11

Need Node        11

Event Node        11

Agent        12

Context setters        13

Templates        14

Unity atoms        14

Runtime        15

Debugging        15

Agent Behaviour        15

Scripting references        16

Conditions/Actions        16

Cache        17

Validation        17

Tags        18

Abilities        18

Needs        19

Events        19

Custom fields (Context, method, condition)        19

Context fields        19

Method fields        20

Condition fields        20

Debugger        21

Set context        21

Graph        21

Global        22

Auto generated code        22

Links/Contact        23


Installing

Unity Versions

The version which is recommended for this editor is 2021.x.x and up.

Download package

Importing the package in your project can be done via the package manager when the package is coupled to your Unity account.

Optional package

The editor also supports the addition of the Unity Atoms package which can be used to fire events within the editor. The required packages for this to work are the base atoms and the core.

https://unity-atoms.github.io/unity-atoms/ 


Quick setup

Setup

When the package has been imported in Unity, an extra tab will show up in the toolbar as “Tools > AI Editor”. This will open the graph. When opening the graph for the first time, the editor will be empty.

A graph can be created inside your project when right clicking in the project. Under

“Create > AI > Main Graph” a main graph can be created. This object will hold all the behaviour data for the AI. Selecting this graph object, will open the behaviour in the editor. When the editor has not been opened, double clicking will open the editor with the selected behaviour.

Create first Graph

The first thing you will see in the graph is the start node. To add new nodes, you can right click within the graph. The main component of the graph is the task node with conditions and actions.

In this task you can add user created conditions/actions in the inspector of the node.

Create first behaviour

To create a custom condition/action a partial class has to be created which inherits from a Condition or AgentAction class. Within this class you can override the function Execute()

This function is called every agent tick where the logic of the agent is located. This function also has the responsibility to set the Status property to determine the state of the condition/action.

There is also a template available to start immediately. “Create > AI > Template”

Exposing variables to the editor is possible with the [ShowInGraph] attribute.


Editor Usage

Structure

The agent is the entity that uses the behaviour graph.

The system is built on graphs which are a collection of tasks. These tasks together create the required behaviour.

Tasks make up the main elements of the behaviour of the Agent. A task can be used in two ways. Or the task is set up to handle conditions or it can handle actions.

The conditions are able to be executed and enable the user to store objects which are found or are a result of the condition check.

The actions are elements which are executed after the conditions together are valid.

These conditions and actions are the custom scripts which the user can write. These conditions and actions can be used only on task nodes. But these components are the foundation on which the system works.

The next important node is the subgraph node in which nested behaviour can be created to make complex systems. These nodes have a subgraph assigned to them, which is user created. There are also other nodes which have special functions which will be explained in the paragraph  “Nodes”.


Editor

Interface

Toolbar

The toolbar consists of buttons to control the basic functions of the editor. The functions include Saving, reloading, importing, focus on nodes, duplicate, node snapping.

Hierarchy

The hierarchy at the top of the editor shows the current path of the graph. The path is relative to the main graph which was selected. Clicking on any of the paths will open the selected graph. The rightmost graph is the current graph. The leftmost graph is the relative root of the current graph.

Inspector

On the right side of the editor the inspector is shown, which functions as a custom inspector for the nodes within the graph. The inspector can be hidden for extra space.

Variables

The left tab displays the graph and global variables. These variables can be set in runtime, or have a default starting value. These variables can be used within the tasks to reference runtime objects. The default values can not reference a scene object.

To add variables this button can be clicked, then selecting the desired type.

The graph variables can also be cleared when they are not in use. The variable is in use when the graph has been saved.

This does not work for the global variables.

Node Field

The main field in the middle displays the nodes.

Controls:

Double click on nodes: default action

Right click on nodes: actions

Left click on nodes: select

Left click on nodes and drag: move selected nodes

Shift + Left click on nodes: additional select

Left click and drag on grid: box select

Middle mouse and drag on grid: move grid and nodes

Scrollwheel: zoom

Ctrl+Q: Action node

Ctrl+W: Condition node

Moving fields

Right-clicking (space) opens node menu

Debugger

The debugger is able to display custom errors which can be sent from within the implemented behaviours. The debugger itself is simple with a couple of options.

Errors have different warning levels, the editor has filters to only view certain errors. These can be toggled to view the selected type of error. The editor can also pause when the debugger receives an error. This can be set by toggling on the error pause button.

The clear button removes all the current messages.


Nodes

There are a couple of nodes which are the building blocks of this AI system.

Input nodes such as the start, event and need nodes provide a way to enter the behaviour cycle. Output nodes which can be an exit or subgraph node. An exit node stops the current active behaviour. A subgraph enters a new behaviour cycle creating an nested behaviour.

Then there are two nodes which execute code, condition and action nodes. These nodes are what make up the bulk of the behaviour of the system.

Each node has a connection point which can have different colours to display their function. The different types includes:

Input                :         white

Success         :         green

Failure          :        red

Finally                :         blue

Combined        :        yellow         :         Not interactable

When clicking on these points a line will appear which can connect other nodes.

Right clicking on the point when a connection is present will clear any connections.

Actions/Conditions

The conditions and actions on the node can be inspected by clicking on the node.

The shown fields are generated based on the tagged fields within the custom behaviour scripts.

Context

The context system is used to reference runtime objects in the editor. The user is responsible for setting these context variables. There are a couple different ways to get context objects.

The first is from conditions, which can emit an object when it has executed its logic. The current and next node can access these variables in a ContextInput field. This field allows the user to assign a context object to the condition or action.

The second way is to add a variable which is accessible from the entire graph. This is the graph variable. These variables are unique for each agent with the same behaviour.

Subgraphs can have separate variables from the main graph.

The last type of context is global which is the same in any graph or agent.

The custom field as mentioned earlier will be discussed later on in the “Scripting Reference” paragraph.

Graph Context

Graph variable fields can be assigned. A default value can be assigned in the editor, these values are the starting value of the graph.

The following types are supported: UnityEninge.Object, Int, Float, String, Vector2, Vector3 and finally a List.

When deleting variables and the variable is in use, a warning is displayed. When deleting the variable, the system will clean all the references within the graph, causing unreferenced

ContextInputs when they referenced that variable.

Clearing the variables will delete any variables that have zero references.

Global Context

The global variables when loading a graph are always the same in every graph. This means any changes cause things to change in every graph. Deleting global variables will cause the graphs to be updated and delete references.


Start Node

The start node can not be created/deleted and is standard in any graph as this node is the entry point for any behaviour.  

Task Node

A task node contains the custom conditions and actions, which will be executed at runtime. By default when a condition fails and it has a fail task assigned it will try again after the execution. In the condition node this type of execution can be changed. The types of check are: Retry, Wait to fail/succeed, or, nor, and, nand, xor and xnor.

The node displays the conditions and actions which are assigned. It also has success/failure/finally points which are executed depending on the exit state of the node. The finally is always called no matter the exit state after the success or failure state.

The collapsed node still displays the status of the conditions and nodes for the debug mode.

In the inspector the user will see the actions and conditions depending on the type of the task node. Clicking on the plus symbol will add an extra condition/action.

Clicking on the min symbol will remove the condition/action from the list.

Opens the script on the behaviour.

Subgraph Node

Sub graph nodes allow for nested behaviours within the behaviour. These nodes contain a reference to a subgraph. These subgraphs can be created by the user and filled with custom behaviour. When the node is encountered at runtime it will execute the behaviour within from the start node.

Creating sub graphs should be done inside the resources folder in order to get the editor to use them in the spawning menu.

Exit Node

The exit node allows the user to go back to the root of the behaviour. By default the exit quits to the root of the current graph, so when in a subgraph it will go back to the entry point.

But when selecting the option in the inspector, the node will quit to the root entry point of the behaviour.

Need Node

The need node is meant to represent the need of the agent, such as hunger or thirst. The node sends out an task assigned in the graph, only when a value has reached below the threshold.

Event Node

The event node is a way to add tasks via external triggers. When assigning an Unity Atom event to the inspector and triggering that event will add the connected task to the agent.


Agent

The agent component can be assigned to any GameObject.

Behaviour

This agent script handles all the logic of executing the assigned behaviour. To give an agent its behaviour, the user can add a graph to the references tab of the agent.

Runtime

The agent has some runtime fields which display the current task list which the agent is going through. It also contains the needs which the agent is using. These values are all copied from the original graph data.

Execution speed

The speeds at which the agent handles the conditions and actions can be set within certain limits. It can also be stepped manually for debugging.  

Ability

Abilities can be assigned to the agent to add custom functionality such as an inventory. These abilities can be accessed from within the agent inspector.


Context setters

The ContextSetter component can be used to automatically set the variables for the behaviours.

The context setter is able to set the global or graph context. Setting this context is done at runtime. Which can be done at OnEnable when set.

When setting the context of a graph an agent can be specified or it will try to set the context for every agent in the scene.

The component will warn the user when the global context can not be found.

The component cannot warn the user when the graph context is set.

Note: The name of the context is case sensitive.


Templates

Under “Create > AI > Templates” the two templates can be found for a condition or action.

These templates provide a quick start to creating a behaviour.

Unity atoms

The graph supports event handling with the use of Unity Atoms. When the package has been installed. From the atoms package only the Core and Base atoms are required for the system to function.


Runtime

Debugging

When selecting an agent while in play mode, the open editor will show the internal state of the agent. The graph will display the name of the agent and a white overlay. The agent has a task list which is shown on the tasks. The status which has been set in the custom conditions and actions is shown in the task with the following colour coding:

Green                :         Success

Red                :         Failure

Dark Blue        :         Pending

Orange        :         Running

Lightblue        :         Waiting

Grey                :         Not in use

The indicators are displayed on the task itself too. When a task is being used it will also display the orange bug indicator.

Agent Behaviour

When initialising the agent, the agent will copy the assigned graph. The agent will ask the graph for tasks when needed.

When the agent does not have any tasks in its list, it will try to add the start task again.

So the behaviour will infinitely repeat.

When the behaviour encounters a subgraph it will open the graph and follow the current task.


Scripting references

Conditions/Actions

The conditions/actions have an Execute() function which can be overwritten to implement your behaviour. The function relies on the user to set the Status property. This status will show up when debugging this behaviour.

To end a condition or action the status can be set to Failure or Success depending on the user’s behaviour.

To show any public variable in the graph inspector of the behaviour the attribute [ShowInGraph]

This will be able to display any of the default inspector elements. Plus some custom fields seen in the paragraf “Custom Fields”.

Getting an object from the context requires the use of the ContextInput class. This will give the option to select a context object which will be resolved at runtime.

To get an object from this input the following function can be used:

ResolveContext(ContextInput, out ContextInstance) 

or

ResolveContext<T>(ContextInput, out T)

This will return an object of the given type.

The ContextInstance is the data container where the object will be stored in. The object can be collected by using <Instance>.obj.

Conditions are able to set the context values. This is mostly used to find objects and then storing that object. To set an object the function:

SetThisContext(object)

Can be used to update the context for the given object’s index.

There are more attributes applicable to the conditions and actions. These will be discussed in the Tags paragraf.


Cache

The executing objects used in the editor are cached, when using these objects the values from the cache need to be copied over. This is automatically done for any variables with the tag [ShowInGraph]. But to load values outside of the

The function:

LoadCache(ICachable)

can be used to load data. This function is called when the task is added to the task list on the agent.

When returning the object to the cache, the function

ReturnCache()

Is called to reset values which were previously set.

Validation

The conditions and actions in the editor can be validated to set custom errors when values are missing. Adding the IValidator interface is required to validate the values in the executing object.

The Validate() function can be used to send errors and a custom message which is displayed as a tooltip. The function returns a tuple with the error type and the custom message string.

return default; can be used to send nothing.


Tags

When adding a condition or action the script will be visible in the task inspector. But these will be unstructured. To group these scripts together the attribute [GraphPath(string)] is used to change under which path the script is grouped under.

To let the editor know what kind of object is sent to the context values. Otherwise the type will be unknown in the graph. This is nothing more than a visual representation and helps in the editor. It does not actually restrict the object which can be stored.

[ContextOutput(Type)]

Abilities

To create an ability the class AgentAbility has to be inherited.

This ability is a scriptableobject on which the system is built.

Variables in the ability do not have to be tagged with [ShowInGraph] to show up in the agent inspector. It uses normal Unity serialisation.

On the agent the following functions exist to handle the abilities.

Check if an ability of a type exists, returns true if the ability is present.

HasAbility<T>()

Get the ability with the given type, outputs the found instance. Returns true if type is found.

GetAbility<T>(out T)

Add an ability to the list of abilities

AddAbility<T>(T)

Remove an ability to the list of abilities

RemoveAbility<T>(T)


Needs

A need has two functions which can be overridden. The function of the need is to add tasks based on a counter. This counter can be manipulated by default in the need node.

Each agent tick the update function is called. With the agent as context and an increment on the timer which is by default 0.

UpdateNeed(Agent, float)

The following function is used by default to add the task to the agent.

AddNeed(Agent)

Note: The [ShowInGraph] tag on variables in an AgentNeed class does not mean the values are initialised automatically.  

Events

The event node uses the Unity Atom package to receive events. These events can be selected in the inspector of the node. The event is automatically subscribed to, and the return object is stored in the context value when called.

Custom fields (Context, method, condition)

Context fields

When using the ContextInput in a condition/action or ContextInstance in a function.

In the editor the field will be visible in the inspector, when clicking on this field the available options will be shown.

Examples

Variable:

[ShowInGraph] public ContextInput input;

Function:

[ShowInGraph]

public void ExampleFunction(ContextInstance instance)

When no context has been selected “<Context>” will be shown.

Method fields

When using MethodHolder objects the editor will automatically display this as a selector for tagged functions seen in the previous paragraph.

To execute the method which has been selected the following function can be used:

ExecuteFunction(AgentExecuter, GameObject)

To Execute this function the object itself is needed and the object on which the selected component can be found.

Condition fields

When using ConditionHolder objects the editor will automatically display this as a field for reflection or variables.

The following two functions are available:

When using the context field

CheckContext(AgentExecuter)

When using the reflection to check a field

CheckReflection(Object)

The types which are the system is able to check are:

float, int and system.object.

But only int and float support more checks other than equal and not equal.


Debugger

To show custom warnings in the debugger of the editor there are some functions to handle the sending of messages. Sending an agent will display the origin of the message by displaying the task. Sending this agent is optional.

Meta.Debug.Log(object, Agent)

Meta.Debug.LogWarning(object, Agent)

Meta.Debug.LogError(object, Agent)

Set context

There are some static functions and extensions to support setting values for the graph. These functions are available in the ContextHelper class.

Graph

There are a couple of extensions to get and set the context value for a particular agent.

There are two functions to get a context value via the out parameter. The functions also return true when a value has been found.

GetGraphContext<T>(this Agent, Task, string, out T)

GetGraphContext(this Agent, string, out object)

A context value can be set with the following function

SetGraphContext(this Agent, string, object)

This function will be able to add the given object to a list value in the context variables.

SetObjectInContextList(this Agent, Object, string)

The context can also be set for all the active agents in the scene, this will update the given object for each agent. This only works for an agent if the agent has the given context name in this graph or subgraphs.

 SetAllAgentsContext(this object, string)

Global

The global context can also be set with the help of some static functions.

To get a global context value this function can be used, also returning true when the variable was found.

GetGlobalContext(string, out object)

Setting a global variable can be done with this function

SetGlobalContext(this object, string)

Setting a value inside a list global variable can be done with this function, these lists only allow UnityEngine.Object to be passed.

SetObjectInGlobalContextList(Object, string)

Auto generated code

When creating conditions or actions, the variables need to be initialised to save changes. This is done by auto generating the necessary code. This file will be generated in the same folder as the condition/action in a new folder called “Generated”.

The user should not interact with this script. But when moving/deleting the accompanying file, it moves or is deleted along with the other file.

NOTE: The conditions/actions should not be moved/deleted outside of the unity project. When doing this, a generated file could be placed in the wrong folder or linger in the project which will throw errors.


Links/Contact

Company: Trive Technology

Tutorial:

Support email: support@trivetechnology.com 

Website: www.Trivetechnology.com