It's always best to plan the structure of a behavior tree before actually implementing it using the Behavior Tree Editor. This not only helps in determining the different nodes required and their position within the tree, but also helps in preventing errors in the tree's design ahead of their occurrence.
This section then is intended to walk users through the design of a very basic behavior tree, that causes an AI character to follow the player when sighted. If and when the AI is unable to follow the player through an area, the character salutes the player.
At the end of each step, an XML representation of the behavior tree is depicted for ease of understanding.
Only interested in knowing how to use the Behavior Tree Editor tool?
Skip this section and move on to the second part of this tutorial, Implementing the Behavior Tree in The Behavior Tree Editor instead.
Every behavior tree must begin with a root node that:
Since the goal of behavior tree here is to have its AI character perform a sequence of actions namely:
The Sequence node is the most appropriate choice of node to be called by the root. Located within the Flow category of nodes in the Behavior Tree Editor, the Sequence node executes each of its children nodes in the order they're defined, one at a time.
Parameters | None. | ||||||
Results |
|
Sequence node configuration
<?xml version="1.0"?>
-<BehaviorTree>
<MetaExtensions/>
-<Root>
-<Sequence>
Events in a behavior tree are used to inform AI agents of the occurrence of specific scenarios within the game, causing them to react accordingly.
In the case of the behavior tree here, the AI character must be notified of when the player is in sight. CRYENGINE comes with a built-in event called OnNewAttentionTarget, which is automatically triggered when the AI detects a target which in this case, is the player.
Since the AI agent/behavior tree must remain idle till the player is sighted, it seems appropriate to use the Time → Wait for Event node; this node works by pausing execution of the tree until a specified event is received.
Parameters |
| ||||||
Results |
|
Wait for Event node configuration
Assuming that the Wait for Event node ceases execution of the behavior tree until the OneNewAttentionTarget event is received, the structure of the tree so far is as follows:
<?xml version="1.0"?>
- <BehaviorTree>
<MetaExtensions/>
- <Root>
- <Sequence>
<WaitForEvent name="OnNewAttentionTarget"/>
The next step is to have the AI agent move towards the target/player when the OnNewAttentionTarget event is received. To do so the GameSDK → Move node is selected, which moves the agent from its current position to a specified destination; this destination is updated if the target is moving.
Parameters |
| |||||||||
Results |
|
Move node configuration
In order to have the AI agent move towards the player (target), the value of the Move node's To parameter is set to Target; additionally, the agent will stop at a distance of 2m from the Target. While all other parameters have been left at their default values, feel free to experiment with alternate ones.
<?xml version="1.0"?>
-< BehaviorTree>
<MetaExtensions/>
- <Root>
- <Sequence>
<WaitForEvent name="OnNewAttentionTarget"/>
- <Move considerActorsAsPathObstacles="0" avoidGroupMates="0" avoidDangers="1" fireMode="Off" to="Target" glanceInMovementDirection="0" strafe="0" turnTowardsMovementDirectionBeforeMoving="0" moveToCover="0" bodyOrientation="Halfway Towards Aim Or Look" stance="Stand" speed="Run" stopDistanceVariation="0" stopWithinDistance="2"/>
In the current behavior tree configuration, the AI agent executes two actions in sequence:
This movement however, will only be performed once; to make the agent to follow the player/target continuously, a Flow → Loop node is added around the Move node to cause it execute infinitely.
Parameters |
| ||||||
Results |
|
Loop node configuration
<?xml version="1.0"?>
-<BehaviorTree>
<MetaExtensions/>
- <Root>
- <Sequence>
<WaitForEvent name="OnNewAttentionTarget"/>
- Loop
- <Move considerActorsAsPathObstacles="0" avoidGroupMates="0" avoidDangers="1" fireMode="Off" to="Target" glanceInMovementDirection="0" strafe="0" turnTowardsMovementDirectionBeforeMoving="0" moveToCover="0" bodyOrientation="Halfway Towards Aim Or Look" stance="Stand" speed="Run" stopDistanceVariation="0" stopWithinDistance="2"/>
The problem with the current structure is that if the player/target is unreachable by the AI agent, for example when the player is outside the agent's Navmesh, the Loop node will fail. This in turn will cause the Sequence node and hence, the Root node to fail, which should not happen.
To avoid this, a Core → Suppress Failure node is added around the Move node so that its execution always succeeds. This in turn ensures that the behavior tree is always running.
Parameters Accepted | None. | ||||||
Results |
|
Suppress Failure configuration
<?xml version="1.0"?>
-<BehaviorTree>
<MetaExtensions/>
- <Root>
- <Sequence>
<WaitForEvent name="OnNewAttentionTarget"/>
- Loop
- <SuppressFailure>
- <Move considerActorsAsPathObstacles="0" avoidGroupMates="0" avoidDangers="1" fireMode="Off" to="Target" glanceInMovementDirection="0" strafe="0" turnTowardsMovementDirectionBeforeMoving="0" moveToCover="0" bodyOrientation="Halfway Towards Aim Or Look" stance="Stand" speed="Run" stopDistanceVariation="0" stopWithinDistance="2"/>
</SuppressFailure>
The goal of our behavior tree however, is not that of simply suppressing failure every time the AI agent is unable to reach its target/the player. It should perform an animation instead, specifically a salute animation, for which reason a GameSDK → Animate node is added to the tree with the following configuration:
Parameters |
| |||||||||
Results |
|
Animate node configuration
In order to ensure that the Move node is executed first with priority, and that the Animate node is executed only when the Move node fails, a Flow → Selector node is used. Since the Selector node executes its children in the order of their definition, one at a time, the Move and an Animate nodes are made its children as follows:
Parameters | None. | ||||||
Results |
|
Selector node configuration
<?xml version="1.0"?>
-<BehaviorTree>
<MetaExtensions/>
- <Root>
- <Sequence>
<WaitForEvent name="OnNewAttentionTarget"/>
- Loop
- <Selector>
- <Move considerActorsAsPathObstacles="0" avoidGroupMates="0" avoidDangers="1" fireMode="Off" to="Target" glanceInMovementDirection="0" strafe="0" turnTowardsMovementDirectionBeforeMoving="0" moveToCover="0" bodyOrientation="Halfway Towards Aim Or Look" stance="Stand" speed="Run" stopDistanceVariation="0" stopWithinDistance="2"/>
- <Animate name="IA_Salute_01" setBodyDirectionTowardsAttentionTarget="0" urgent="1" playMode="PlayOnce"/>
</Selector>
</Loop>
</Sequence>
</Root>
</BehaviorTree>
At this point, the behavior tree is complete and its sequence is as follows:
The structural design of the behavior tree is now complete. Now to implement it in the Behavior Tree Editor, and link it to an AI character in the next section of this tutorial.