Sequences
A Sequence ticks all its children as long as they return SUCCESS. If any child returns FAILURE, the sequence is aborted.
Currently the framework provides three kinds of nodes:
- Sequence
- SequenceWithMemory
- ReactiveSequence
They share the following rules:
Before ticking the first child, the node status becomes RUNNING.
If a child returns SUCCESS, it ticks the next child.
If the last child returns SUCCESS too, all the children are halted and the sequence returns SUCCESS.
To understand how the three ControlNodes differ, refer to the following table:
Type of ControlNode | Child returns FAILURE | Child returns RUNNING |
---|---|---|
Sequence | Restart | Tick again |
ReactiveSequence | Restart | Restart |
SequenceWithMemory | Tick again | Tick again |
"Restart" means that the entire sequence is restarted from the first child of the list.
"Tick again" means that the next time the sequence is ticked, the same child is ticked again. Previous siblings, which returned SUCCESS already, are not ticked again.
Sequence
This tree represents the behavior of a sniper in a computer game.
ReactiveSequence
This node is particularly useful to continuously check Conditions; but the user should also be careful when using asynchronous children, to be sure that they are not ticked more often that expected.
Let's take a look at another example:
ApproachEnemy
is an asynchronous action that returns RUNNING until
it is, eventually, completed.
The condition isEnemyVisible
will be called many times and,
if it becomes false (i,e, "FAILURE"), ApproachEnemy
is halted.
SequenceWithMemory
Use this ControlNode when you don't want to tick children again that already returned SUCCESS.
Example:
This is a patrolling agent/robot that must visit locations A, B and C only once. If the action GoTo(B) fails, GoTo(A) will not be ticked again.
On the other hand, isBatteryOK must be checked at every tick,
for this reason its parent must be a ReactiveSequence
.