How to use Behaviour Tree Editor

Opening the editor

The Behavior Tree Editor can be accessed by either double-clicking an existing tree asset or through the tab located in AnythingWorld -> Behavior Tree Editor.

Behaviour Tree Editor can be opened via double clicking on existing tree asset or opening the tab in AnythingWorld -> Behaviour Tree Editor.

User interface overiew

Node View

Displays behavior tree nodes and the edges connecting them. This area allows users to interact with the nodes, connect them to each other and visualize the tree structure.

Node Inspector

Shows data associated with the currently selected node. Some fields are presented as dropdowns linked to blackboard keys, they have a special type of NodeProperty which allows them to interact with blackboard keys. Other fields are standard Unity serialized fields.

Working with nodes

Adding a node

To add a node, right-click on anywhere in the node view and select the desired node from the context menu. You can also start typing the name of the node to filter the list.

Editing node code

Double-clicking on a node opens the code associated with it, allowing direct modifications to its behavior.

Auto-scaling

Pressing "A" will auto-scale the node view to occupy the available window space fully, enhancing visibility.

Behaviour Trees management

Accessing behaviour trees

Clicking on the Asset menu in the upper left corner reveals a list of all behavior trees in the current project and provides an option to create new ones.

Global settings

  • New nodes and trees are saved to default locations specified in the global BT settings, found at Assets/AnythingWorld/AnythingBehaviour/BehaviourTreeProjectSettings.asset.

  • Enable Node Values Copying setting determines whether node's field values will be deep copied when copy pasting nodes in node view.

Deep copy works for most of the Unity and basic types. However, more complex ones like Lists of custom types may fail. In this case a warning will be shown and the value skipped.

Integration and runtime behaviour

Adding to GameObjects

  • To use a behavior tree with a GameObject, add the BehaviourTreeRunner component and select the appropriate tree. Once you add a tree it is automatically instantiated so you can edit it without changing the original asset.

  • BehaviourTreeRunner also allows adding blackboard overrides for any blackboard keys BT has. This is useful if you want to change parameters like speed without opening and editing a BT.

  • Overrides are applied when entering playmode so they need to be setup beforehand.

Note that override will not work if any of the nodes write a value to that key effectively overwriting the value that you set in BehaviourTreeRunner.

  • Animated models in AnythingWorld Model Browser are imported with preset movement BTs depending on the model type. These default BTs can be changed via Make Options. You can also enable NavMesh usage which will make ground animals move using existing NavMesh or a generated one in case there is none in the scene.

Execution flow visualization

When a scene is played, a runtime copy of the tree is created. If you've opened a Behaviour Tree Editor window before running the scene,d clicking on a GameObject with an active tree will visualize the execution flow, with colors indicating the state of each node. Yellow denotes nodes that returned Running state, green - nodes that returned Success state and red - nodes that returned Failure.

Compatibility

Behavior trees should be created in the lowest Unity version they will be used with, as there is no downward compatibility between versions. You can see the lowest Unity version AnythingWorld currently supports here.

Extending Behaviour Tree with code

Adding new node types

New node types can be added either through the context menu in the node view or by creating a new C# class that inherits from Action, Decorator, or Composite types. These classes must implement OnStart(), OnStop(), and OnUpdate() functions, with OnUpdate() returning one of the node states.

Shared context

Each node class has access to a shared context field which is an instance of Context class that stores commonly used components and subsystems. It is created from the game object that you attached BehaviourTreeRunner component to. You can extend it by adding components that you want all nodes to have access to like Colliders, RigidBodies, etc.

Converting field to NodeProperty to enable blackboard interaction

To enable any field of a node to read or write to a blackboard key you must declare it as a NodeProperty<T> where T is the type of the property you want to declare, e.g. NodeProperty<float> speed. You can set a default value via constructor like so: NodeProperty<float> speed = new NodeProperty<float>(4). If you have a blackboard key of the same type it's possible now to associate speed NodeProperty with that key by choosing it from a dropdown in Node Inspector.

Converting a field into a NodeProperty and connecting it to a blackboard key will also allow you to override its value in the BehaviourTreeRunner component as discussed earlier.

Adding new blackboard key types

Opening Type dropdown when creating a new key will show most of the common C# and Unity types. However if you find some types lacking you need to add them manually by opening BlackboardKeyTypes.cs file and adding your type following the existing pattern.

Since the blackboard view extends the default Unity inspector it should be able to show all the types Unity inspector supports. However, adding more complex custom types can lead to rendering as well as reading \ writing problems. They can be fixed in some cases but will require in-depth editing of Behaviour Tree Editor code.

Moving agents with behaviour trees

You can find example random movement BTs for all types of AnythingWorld agents underAssets/AnythingWorld/Examples/BTMovement. To see them in action open and run RandomMovement scene from the same folder. There is also MoveAlongSpline BT which is explained in Path Creator documentation section.

All the random movement BTs follow the same logic:

  1. Generate a random position via random position node.

  2. Write it into a blackboard key.

  3. Use that position as movement destination in a MoveToDestination node.

  4. Wait before generating a new position.

However these nodes and their settings vary depending on the model type. The only variables common to all movement nodes and goal generation nodes are the following:

  • Min / Max Goal Spawn Radius - min / max random goal distance from agent's position.

  • Speed - initial speed of the agent.

  • Scale Speed With Model Speed - should we multiply the Speed by speedScalar? speedScalar is calculated from speed data specific to imported model.

  • Stopping Distance - the remaining distance to the goal when the agent stops moving and considers the goal reached.

Ground agents movement

Both ground animals and vehicles have settings for movement and turning speed. However ground animals are also able to jump hence GroundAnimalMoveToGoal node in GroundAnimalRandomMovement tree has additional jump settings explained below:

  • Jump Detector Size - the distance at which an agent will try to detect an obstacle and either avoid it or jump on it. Consequently determines the distance between jump starting point and obstacle.

  • Scale Jump With Model Height - will decrease or increase both Max Jump Height and Jump Detector Size proportional to model's height.

  • MaxSlope - maximum slope of the surface an animal able to traverse. Any surface with slope above max is processed as an obstacle that will be avoided or jumped on.

You will notice that the movement node of GroundAnimalNavMesh tree has almost no jump settings. That's because NavMesh is used to calculate optimal routes and there cannot be arbitrary changes to movement trajectory. Jump areas must be explicitly defined via NavMeshLinks explained here.

Flying and swimming agents movement

While movement speed and rotation settings resemble previously discussed agents, goal generation has an added height constraint. Flying agent's AerialRandomGoal node has:

  • Ground Y Coordinate which defines the ground level with global Y coordinate.

  • Min / Max Flying Height - min / max height relative to ground. So if you have ground level set at 5 and min height set at 2, the agent's min flying height will be 7.

Swimming agents are similar but always stay below water surface. Hence FishRandomGoal node has only Surface Y Coordinate and Swimming Depth which is also relative to the surface.

Last updated