- Advanced State Machines
- Hierarchical states, state stacks, and context passing define complex behavior management.
- Available Scripts
- hsm_logic_state.gd
- Expert HSM base class with state stack management and validation.
- pushdown_automaton.gd
- Stack-based state machine for interrupt-resume behavior (pause menus, cutscenes).
- MANDATORY
- Read hsm_logic_state.gd before implementing hierarchical AI behaviors. NEVER Do in Advanced State Machines NEVER forget to call exit() before enter() — Transition without exit? Previous state cleanup skipped = resource leaks (timers, tweens). ALWAYS exit → enter. NEVER use push_state() without pop_state() — Pushed 100 interrupt states? Stack overflow + memory leak. EVERY push needs matching pop. NEVER modify state during transition — transition_to() called inside exit() ? Re-entrant transition = undefined behavior. Flag transitions, execute after current completes. NEVER skip state validation — transition_to("AttackState") but state doesn't exist? Silent failure OR crash. Validate state exists before transition. NEVER forget to process child states — Hierarchical state with sub-states? Parent update() must call current_child_state.update() for delegation. NEVER use string state names in code — transition_to("Idel") typo = silent failure. Use constants OR enums: transition_to(States.IDLE) .
hierarchical_state.gd
class_name HierarchicalState extends Node signal transitioned ( from_state : String , to_state : String ) var current_state : Node var state_stack : Array [ Node ] = [ ] func _ready ( ) -> void : for child in get_children ( ) : child . state_machine = self if get_child_count ( )
0 : current_state = get_child ( 0 ) current_state . enter ( ) func transition_to ( state_name : String ) -> void : if not has_node ( state_name ) : return var new_state := get_node ( state_name ) if current_state : current_state . exit ( ) transitioned . emit ( current_state . name if current_state else "" , state_name ) current_state = new_state current_state . enter ( ) func push_state ( state_name : String ) -> void : if current_state : state_stack . append ( current_state ) current_state . exit ( ) transition_to ( state_name ) func pop_state ( ) -> void : if state_stack . is_empty ( ) : return var previous_state := state_stack . pop_back ( ) transition_to ( previous_state . name ) State Base Class
state.gd
class_name State extends Node var state_machine : HierarchicalState func enter ( ) -> void : pass func exit ( ) -> void : pass func update ( delta : float ) -> void : pass func physics_update ( delta : float ) -> void : pass func handle_input ( event : InputEvent ) -> void : pass Best Practices Separation - One state per file Signals - Communicate state changes Stack - Use push/pop for interruptions Reference Related: godot-characterbody-2d , godot-animation-player Related Master Skill: godot-master