In this lesson, you will learn how to architect a Hierarchical State Machine (HSM) by nesting sub-states within parent states to handle complex behaviors like modular combat logic.
The Concept of Nesting
A standard Finite State Machine (FSM) becomes unwieldy when you have "Combat" logic that includes attacking, dodging, and blocking. Instead of creating a flat list of states (e.g., State_Combat_Attack, State_Combat_Dodge), we use a hierarchy. The Parent State handles general logic applicable to all sub-states, while the Active Sub-State handles the granular behavior.
Implementing the Hierarchy
Think of the Parent State as a "Container." When your AI enters State_Combat, it is effectively "in" that state, but it then delegates execution to a sub-state.
In your C++ state machine, you can represent this by giving your state base class a pointer to a ChildState.
// Inside your State base class
void UAIState::TickState(float DeltaTime) {
if (ActiveSubState) {
// Delegate logic to the specialized sub-state
ActiveSubState->TickState(DeltaTime);
} else {
// Run general parent logic
PerformGenericAction();
}
}
Flow of Control
- Entry: When the AI enters
State_Combat, it initializesState_Attackas theActiveSubState. - Execution: The state machine calls
TickStateonState_Combat. Because it has a sub-state, it forwards the call toState_Attack. - Transition: If the AI needs to dodge,
State_Combatsimply swaps theActiveSubStatefromState_AttacktoState_Dodge. The parent state remains active, meaning you don't have to re-evaluate entry conditions for the combat "zone."
This approach reduces code duplication. For example, if you need a "Stunned" check that applies to all combat moves, you only write it once in the State_Combat parent, rather than duplicating it inside Attack, Dodge, and Block. By nesting logic, you keep your state machine clean, scalable, and easier to debug when your AI's decision tree grows beyond simple idle-to-chase transitions.
Key Takeaway: Use a hierarchical structure to delegate granular behavior to sub-states while maintaining shared logic and context within a single parent state.