How do you build complex behaviors without them becoming too complicated? Most modern games require intelligent and realistic actors to support the design, but it’s often difficult to create their AI.
One solution to this problem is to use modularity to assemble behaviors from simpler parts. Previously, you learned about sequences, selectors and parallels. These are “composites” that combine multiple behaviors together, but sometimes it’s necessary to add features to a single behavior. That’s what a decorator is for.
Decorating a leaf behavior in the tree.
What Is a Decorator?
A decorator adds functionality to any modular behavior, without necessarily knowing what it does. In a sense, it takes the original behavior and adds decorations, i.e. new features. The name is inspired by the software design pattern.
In the context of a behavior tree, a decorator can be inserted anywhere but as a leaf, since it requires a child behavior to improve its functionality. But technically, it’s not a branch either as it only has one sub-tree. In essence, it’s an extension to a sub-tree which creates a more complex behavior.
Types of Decorators
A decorator is a class of nodes in the behavior tree; it does not implement any specific features. In fact, the default decorator would be an identity operation which does not modify the child behavior in any way.
More interesting examples of decorators are:
These prevent a behavior from activating under certain circumstances.
Limit the number of times a behavior can be run.
Prevent a behavior from firing too often with a timer.
Temporarily deactivate a behavior by script.
Restrict the number of behaviors running simultaneously.
Managers & Handlers
These are decorators that are responsible for managing whole subtrees rather than single behaviors.
Deal with the error status code and restart planning or execution.
Store information for multiple child nodes to access as a blackboard.
These decorators are used to pretend that the execution of the child node happened differently.
Force a return status, e.g. always fail or always succeed.
Fake a certain behavior, i.e. keep running instead of failing or succeeding.
Such decorators are useful during development, and can be inserted into a tree automatically when needed.
Debug breakpoint; pause execution and prompt the user.
Logging; track this node execution and print to the console.
The decorators that modify control flow are typically useful when creating the structure of the tree, along with the other composites like sequences and selectors. But once it’s in place, the fine tuning can start.
Most of the other decorator types listed above are used for making such minor changes to the behaviors. They can be inserted harmlessly at any place in a behavior tree. A visual editor can support commands such as Decorate Selected Node which can be applied locally in a safe and predictable way.
This approach makes it much easier to create complex trees for virtually any behavior designers can dream of.
Does your AI have the equivalent of decorators?