- The player avatar actions are most likely controlled by state machines as well, allowing straightforward communication between camera logic and avatar logic
- The animation state machine systems are intended for seamless transitions unlike Behavior Tree which is intended for discrete and immediate AI changes
- The implementation of state machines in Unreal Editor 4 has high usability, with many user interface features that provide relevant information at a glance
- Unlike Behavior Tree's which either go to the Root or the next sibling in a Sequence, State Machines are capable of transitioning between any two states
There are practical limitations to using the animation state machines for any camera system that allows real time control by the player. While it would be possible to rip apart the state machine graphical display elements and make their code work with camera behaviours, vanilla Unreal Editor 4 state machines are only compatible with skeletal meshes. This is a common limitation of state machine visual scripting modules because they are often streamlined for animation. As a result, we see similar limitations when using Unity's Mecanim: it is built for blending and transitions between animations that have exact definitions where cameras require adaptive behaviours to address their "fuzzy" constraints.
Let's put the implementation of state machine modules aside and look for proof that behaviour trees bestow more flexibility for camera behaviours than any ideal state machines. The purpose of this experiment is to use nonfunctional examples to compare Unreal's implementation of Behavior Trees and State Machines for similar camera behaviours. The "Sense" and "Act" aspects of behaviours were not created.
Our starting point for this experiment is any project with Animation Starter Pack, which can be added to your project for free from Epic Games in the Marketplace.
Experiment: Flexibility in iteration
The subject (me) will determine how many steps it takes to add a crawling camera to a camera state machine based on UE4ASP_HeroTPP_AnimBlueprint. Then they will assess the same criteria when crawling is added to a camera behaviour tree.
Use case: Late in development, a producer asks the gameplay team to add crawling to the stealth system and a camera artist must add camera behaviour to support it.
What assumptions are we making?
For this experiment we are assuming that the state machine for the camera would match the simple state machine for this demonstration projects' player avatar animations. We are also assuming that the corresponding behaviour tree would not require a one-to-one relationship in terms of states and re-uses the same module with encapsulated transitions for each similar state. Since I am not yet a power Behavior Tree user, we are also assuming my nonfunctional Behavior Tree is valid as it cannot be tested. The Crawl state will be accessible from any stationary behaviour state with a single button press, and stays in third person camera until the transition to Crawl Walk when the player moves.
How are we evaluating flexibility?
1. How many connections must be broken and formed to add the crawling state? An increased number of alterations to existing connections indicates low flexibility because each change has a greater impact and a higher likelihood of causing bugs.
2. How many new nodes are required, and what is the total number of nodes? More nodes added does not necessarily indicate less flexibility but if numbers increase significantly with each alteration, then the graph can become unmanageable.
3. How many total clicks for this test and clicks per node added? Again, we are assessing how a perfectly knowledgeable user would accomplish the final result. Lower clicks indicate higher flexibility. A high number of clicks per node added is an indicator that the system takes more effort to change and is therefore less flexible.
The results will be completely quantitative, but small differences between the approaches should not be considered important. Only large deltas are significant.
Results: State Machines
1. No connections are broken but 6 new connections are formed.
2. Two new nodes are created for a total of 9 nodes.
3. The number of click and drags required to place the nodes is 8, but we were unable to assess the amount of clicks required to edit the transition properties. In addition, the names of the events fired at each state would have to be typed in. There were four clicks per node before setting properties on states and transitions.
Results: Behavior Trees
1. No new connections were made or broken. The structure of the graph before and after the change is exactly the same. Only the decorator properties were updated.
2. No new nodes were created, however, all relevant execution nodes required changes on the engineering side. The "Think" functionality is exactly the same for choosing between Crouch and Crouch Walk as it is between Crawl and Crawl Walk, or even Idle and Jog. By making "Sense" and "Act" funtionality context dependent, the behaviour tree implementation of "Think" does not need to be updated as often.
3. Once again, we are unable to assess the amount of property changes required to functionally change the Decorators on these nodes to work with the Crawl state. The number of clicks required to change the graph structure was zero.
Conclusion: Flexibility from reusable modules
- Ideal state machines require more connections added than ideal behaviour trees when a new feature is added. There was a significant difference here.
- Ideal state machines require the creation of new nodes by the camera artist, but an ideal behaviour tree does not. This test did not generate significant results.
- The results are inconclusive for number of clicks, but the complexity of default properties available for any State Machine's States and Transitions is high. Functional Behavior Trees have exposed properties on Decorators and Tasks, but default properties to cover most situations could be set by the engineers.
This experiment suffers from using non-functional examples, but serves to illustrate a point: when behaviour trees are implemented well the first time, their graphs do not need to change much to accommodate new features. This is why behaviour trees are considered very flexible in comparison to state machines which are best used to deliver features that require a high degree of specificity.
Note that in a real life example, we may have seen cases where the Crawl state's "Think" functionality did not match the existing Crouch and Standing states exactly. This could have meant reworking the entire graph and possibly causing bugs in both Crouch and Standing states. But with properly engineered Tasks and Decorators, this risk would be minimized.
Refining this experimental method must wait until I can create functional examples to compare state machines with behaviour trees. Since State Machines in Unreal Editor 4 are specialized for an area outside my focus, this will not happen soon.
Bonus Content:
Alex J. Champandard from aigamedev.com