Behavior Tree (Behavior Tree)

To introduce the basic concept of behavior tree through an example, it will be easier to understand, see the following figure:

bv-tree-1

This is a behavior tree that we defined for a soldier (we don’t care what these green circles and red circles do). First of all, we can see that this is a tree structure graph with root nodes, branches, and sub The number of nodes can be arbitrary, and then there are three branches, namely Patrol, Attack, and Retreat. These three branches can be regarded as the three big behaviors we defined for this soldier. Of course, if there are more behaviors, we can continue to add new branches in the root node. When we want to decide what kind of behavior the current soldier should do, we will search the tree through some conditions from top to bottom, and finally determine the behavior (leaf node) that needs to be done, and execute it . It is the basic principle of behavior trees.

It is worth noting that the three behaviors we identified are actually not the result of real decision-making. They are just a type to help us understand that some behaviors of this branch belong to this category. The behaviors of the real behavior tree are all in the leaves. The nodes are generally called Action Nodes, as indicated by the red circle in the following figure

bv-tree-action-node

These leaf nodes are the results of our decision-making through the behavior tree. If described by the hierarchical AI structure I mentioned earlier , these behavior results are equivalent to a defined "request" (Request) , Such as moving (Move), doing nothing (Idle), shooting (Shoot) and so on. So the behavior tree is a kind of decision tree to help us search for a certain behavior we want.

Behavior nodes are game-related. Because of different games, we need to define different behavior nodes, but for a game, the behavior nodes in the behavior tree can be reused, such as moving. On the patrol branch, you need It is used on the escape branch. In this case, we can reuse this node. Behavior nodes are generally divided into two operating states:

  1. Executing: The behavior is still being processed
  2. Completed (Completed): the behavior processing is completed, success or failure

Except for the behavior nodes, the rest are generally called Control Nodes. In the "scientific name" of the tree, they are the parent nodes, as shown by the green circle in the figure below

bv-tree-control-node

The control node is actually the essence of the behavior tree. We want to search for a behavior. How to search? In fact, it is defined by these control nodes. From the control nodes, we can see the logical trend of the entire behavior tree. Therefore, one of the characteristics of the behavior tree is its logical visibility.

We can define a variety of control nodes for the behavior tree (this is also one of the interesting places of the behavior tree). Generally speaking, there are three commonly used control nodes:

  1. Selector: select one of its child nodes to execute
  2. Sequence (Sequence): execute all its child nodes in turn, that is to say, after the current one returns to the "complete" state, then run the first child node
  3. Parallel: run all of its child nodes once

If you use a graph to represent it, it is like this, followed by selection, sequence and parallel

bv-tree-sel

bv-tree-seq

bv-tree-pal

It can be seen that the control node actually "controls" its child nodes (child nodes can be leaf nodes or control nodes, the so-called "execution control node" is to execute its defined control logic) how to be executed, so we Many other control nodes can be expanded, such as loops. Unlike the behavior node, the control node has nothing to do with the game, because it is only responsible for the control of the behavior tree logic and does not involve any game code. If it is used as a behavior tree library, it will definitely contain a defined control node library.

If we continue to examine the selection node, a question will arise, how to choose from the child nodes? What is the basis for selection? Here we will introduce another concept, which is generally called a precondition. Every node, whether it is a behavior node or a control node, will contain a precondition, as shown in the figure below

bv-tree-precondition

The premise provides the basis for "selection". It contains the conditions for entering or selecting this node. When we use the selection node, it is to test the premise of each child node in turn. If it is satisfied, select this node. Since what we ultimately return is a certain behavior node (leaf node), the "total" premise of the current behavior can be regarded as:

The current premise behavior of nodes  And  the premise of the parent node  And  the parent node's parent premise  And .... And  the premise of the root node (usually no direct return True)

The behavior tree describes the decision logic of the entire AI through behavior nodes, control nodes, and premises on each node. For each tick, the following process can be used to describe:

action = root.FindNextAction(input);
if action is not empty then
action.Execute(request,  input)  //request是输出的请求
else
print “no action is available”

Conceptually, the behavior tree is relatively simple, but for AI programmers, it is full of appeal. Some of its features, such as visual decision logic, reusable control nodes, and low logic and implementation. Coupling, etc., compared with traditional state machines, can greatly help us organize our behavior decisions quickly and conveniently. I hope this brief introduction will be helpful to everyone. I have limited ability and may not be able to express it clearly. If there are questions or suggestions, please communicate with me. Finally, I drew a picture of the patrol branch of this soldier. A schematic diagram for your reference:

S — select node Se — sequence node

bv-tree-patrol-example

Some basic concepts of behavior trees, including behavior nodes, control nodes (selection, sequence, parallel), this time, I will discuss some of the behavior trees in more depth. If you don't know much about behavior trees, please refer to here .

1. Discussion on selecting nodes

We said that the definition of selecting a node is to select a node for execution by judging the prerequisites of the child nodes, which involves the issue of judgment order, whether it is from left to right, or randomly, or some other rules, etc., so that Extend a variety of selection nodes.

 

 

  • Priority Selector : This type of selection node is selected from left to right each time. When an executable child node is found, it stops searching for subsequent child nodes. With this selection method, there is a priority problem, which means that the leftmost node has the highest priority because it is judged first. For this kind of selection node, the prerequisite setting of its child nodes must be "from narrow to wide", otherwise subsequent nodes will "starve to death", which means they will never be executed. For a clearer explanation, look at the first picture below. The three child nodes are under a priority selection node , and their premises will be judged in turn. You can see that the premises of the three child nodes are from left to right, one More strict than one, if we now have a as 9, the first child node will be executed according to the definition in the figure below, if a is 7, the second child node will be executed, and if a=11, the third child node will be executed . The second picture below demonstrates a situation where the node "starvation" (Starvation), we see that the premise of the first child node is broader than the second child node, as long as a<10, then from left to right If you judge, you will always enter the first node, so if you want to use a priority selection node , you must check the premise of each child node to prevent the node from starving.

 

bv-tree-priority-selector-1

bv-tree-priority-selector-2

  • Non-priority Selector : The selection order of this selection node is to select from the last executed child node. If the prerequisite is met, then continue to execute this node, if the condition is not met, then from then on At the beginning of the node, the premise of each child node is judged in turn, and when a child node that meets the condition is found, the node is executed. This method is based on an assumption called "continuity", because in a game, a behavior generally does not end in one frame, but will last for a period of time, so sometimes for optimization purposes, we can Judge the last executed node first, and when its condition is not met, look for the next executable node. This search method does not have the problem of which node is judged first, so the requirement for the setting of the premise is to ensure "exclusion". If we use the first picture above to illustrate, if we change the control node to a selection node without priority , we can see that when a=3, the second child node will be executed, and the next time a becomes At 9 o'clock, since the premises are not judged sequentially from the beginning, we will still choose the second node instead of the first node we might expect. The correct approach is shown in the figure below. Note that the premise of each child node is "mutually exclusive". So for the selected node without priority, the order of its child nodes is not so important, and it can be arranged arbitrarily.

bv-tree-nonpriority-selector-1

  • Weighted Selector : For this type of selection node, we will pre-mark a "Weight Value" for each branch, and then when we choose, we will select it by random selection. When random, it will refer to the weight and ensure that the nodes that have been tested will not be tested again until the premise of a node is met, or all nodes are tested. The weighted selection node has the random existence of the sub-node premise, so the premise of the child node can be arbitrary, and the situation of "starvation" will not occur. Generally speaking, we usually set the premise of all the child nodes to the same , In order to better show the probability effect brought by the weight. When the weights of all child nodes are the same, this selection node becomes a random selection node (Random Selector) . The selection node with weights is very suitable for places that need to enrich AI behavior, such as in development games. When a dog is happy, there may be various behaviors. We can use this selection node and add various child node behaviors to achieve it.

bv-tree-weighted-selector-1

These are the commonly used selection node types. We can define more selection node selection behaviors according to our needs. In fact, we can see that different selection behaviors have slightly different requirements for the sub-node premises. This is in our construction Things to pay attention to when performing behavior trees.

2. Discussion on the end conditions of parallel nodes

Each of our nodes will have a running state to indicate whether the current behavior is over. For the control node, its running status is the running status of its child nodes. It is easier to select nodes and sequence nodes, because for these two types of control nodes, only one child node is running at a time. Return the status of the running child node. But for a parallel node, it will have multiple child nodes running at the same time, so how do we deal with the running status of the parallel node? There are generally two types:

  • And: Only when all child nodes have finished running, will it return to the end.
  • Or: As long as one of the child nodes ends, return to the end.

Why do we need to have the running status of the node?

  • In the sequence control node, the running state is needed to control the execution of the sequence
  • The outside world needs to know the running state of the behavior to decide whether to update the decision (if the behavior tree is in the decision layer)/request (if the behavior tree is in the behavior layer). For AI layering, please refer to here

For the second point, you can give an example. For example, if we have a behavior "walk to point A", assuming that this behavior cannot be interrupted, then when we are walking to point A, the running state of the behavior tree is "Executing", when reaching point A, the behavior tree will return "completed", so that, to the outside, when we see that the behavior tree is "executing", we don't need to do any new behavior (For optimization, or for behavior jitter, etc.), when we see "completed", we can make new decisions or behaviors. Such a running state also helps us to detect the state of the behavior tree and help debugging.

3. Discussion on specific realization

There can be various implementations of behavior trees. I have some suggestions here. Generally speaking, each node of the behavior tree needs to have enter (Enter), exit (Exit), run (Execute) and other parts, and a behavior node ( ActionNode), control node (ControlNode), precondition (Precondition) and other base classes, and then you need to define the input (InputParam) and output (OutputParam) of the behavior tree. Generally speaking, we hope that the behavior tree is a black box, that is That said, it only relies on predefined inputs. The input can be Blackboard, Working Memory and other data structures, and the output can be Request or other custom data structures, as shown below:

bv-tree-arch

Revolutionary Unity Editor Extension Tool --- Odin Inspector series of tutorials

https://www.jianshu.com/p/f1b27e85bc35

NodeCanvas

https://nodecanvas.paradoxnotion.com/

Behaviour Trees

State Machines

Guess you like

Origin blog.csdn.net/Momo_Da/article/details/112960916