godot-state-machine-advanced

$npx mdskill add thedivergentai/GD-Agentic-Skills/godot-state-machine-advanced

Implements hierarchical state machines and pushdown automata for complex AI behaviors.

  • Manages layered AI behaviors where basic FSMs are insufficient.
  • Depends on Godot 4.7+ and provided HSM scripts.
  • Validates transitions and propagates physics/input through state hierarchy.
  • Delivers reusable state machine scripts with context passing and stack management.

SKILL.md

.github/skills/godot-state-machine-advancedView on GitHub ↗
---
name: godot-state-machine-advanced
description: "Expert blueprint for hierarchical finite state machines (HSM) and pushdown automata for complex AI/character behaviors. Covers state stacks, sub-states, transition validation, and state context passing. Use when basic FSMs are insufficient OR implementing layered AI. Keywords state machine, HSM, hierarchical, pushdown automata, state stack, FSM, AI behavior."
---

## Godot 4.7 Baseline

- Expert patterns in this skill target **Godot 4.7+** (stable, 2026-06-18).
- Consult the [Godot 4.7 migration guide](https://docs.godotengine.org/en/4.7/tutorials/migrating/upgrading_to_godot_4.7.html) when upgrading projects from 4.6.
- **NEVER** assume 4.6 defaults (stretch mode, audio area_mask, RichTextLabel percent flags) without checking 4.7 migration notes.

# Advanced State Machines

Hierarchical states, state stacks, and context passing define complex behavior management.

## Available Scripts

### [hsm_hierarchical_base.gd](scripts/hsm_hierarchical_base.gd)
Advanced HSM base delegator for propagating physics and input to sub-states.

### [hsm_pushdown_stack.gd](scripts/hsm_pushdown_stack.gd)
Professional Pushdown Automata for interruptive state (Pause/Menu) stacking.

### [hsm_state_context.gd](scripts/hsm_state_context.gd)
Decoupled context object pattern for passing persistent data between states.

### [hsm_transition_guard.gd](scripts/hsm_transition_guard.gd)
Expert transition validation logic to prevent illegal state changes.

### [hsm_animation_syncer.gd](scripts/hsm_animation_syncer.gd)
Automated Logic-to-AnimationTree syncing with state-based travel logic.

### [hsm_concurrent_logic.gd](scripts/hsm_concurrent_logic.gd)
Orchestration for parallel state machines (e.g., Move + Attack).

### [hsm_resource_state_loader.gd](scripts/hsm_resource_state_loader.gd)
Data-driven state definition using custom Godot Resources (`.tres`).

### [hsm_reentry_aware_state.gd](scripts/hsm_reentry_aware_state.gd)
Handling resume-from-stack logic vs fresh entry events.

### [hsm_state_history_logger.gd](scripts/hsm_state_history_logger.gd)
Debug ring-buffer for tracking state transition history and stack depth.

### [hsm_state_timer_component.gd](scripts/hsm_state_timer_component.gd)
Auto-transition component for finite states like Stun or Dash.

> **MANDATORY**: For hierarchy / pushdown / guards read [hsm_hierarchical_base.gd](scripts/hsm_hierarchical_base.gd), [hsm_pushdown_stack.gd](scripts/hsm_pushdown_stack.gd), [hsm_transition_guard.gd](scripts/hsm_transition_guard.gd) (plus [hsm_logic_state.gd](scripts/hsm_logic_state.gd) for leaf behaviors).

## Decision Tree — Which Machine?

| Need | Choose | **MANDATORY** scripts |
|------|--------|------------------------|
| Few exclusive states, no nesting | Flat FSM | [hsm_logic_state.gd](scripts/hsm_logic_state.gd) + thin parent |
| Nested sub-states (Move/Air/Attack children) | HSM | [hsm_hierarchical_base.gd](scripts/hsm_hierarchical_base.gd) |
| Interrupt overlays (stun/menu/dialogue) then resume | Pushdown | [hsm_pushdown_stack.gd](scripts/hsm_pushdown_stack.gd) + [hsm_reentry_aware_state.gd](scripts/hsm_reentry_aware_state.gd) |
| Parallel concerns (locomotion + weapon) | Concurrent | [hsm_concurrent_logic.gd](scripts/hsm_concurrent_logic.gd) |
| Pick best action by score each tick | Utility cost polling | Expert pattern §3 + [hsm_transition_guard.gd](scripts/hsm_transition_guard.gd) |

## NEVER Do (Expert State Rules)

### Hierarchy & Delegation
- **NEVER forget to propagate physics/input to children** — In an HSM, failing to call `child.physics_update()` from the parent's `_physics_process` orphans child logic.
- **NEVER use deep nesting (>3 levels)** — Extreme hierarchy creates "State Spaghetti." If logic is that complex, consider a Behavior Tree or Utility AI.

### Transitions & Lifecycle
- **NEVER call enter() without a preceding exit()** — Skipping exit logic leaves timers, tweens, or audio loops running in the background, causing resource leaks.
- **NEVER modify state during a transition frame** — Re-entrant `transition_to()` calls inside `enter()` cause recursion crashes. Use `call_deferred` if immediate sub-transitioning is required.
- **NEVER hardcode state names as strings** — Typos like `transition_to("Idel")` are silent killers. Use `class_name` based checks OR Constants.

### Architecture & Context
- **NEVER use global singletons for state data** — Coupling states to `GameManager.player_health` makes them non-reusable. Pass a `Context` object.
- **NEVER push states indefinitely** — In a Pushdown Automaton, every `push_state` MUST have a retirement plan (`pop_state`) to avoid stack overflow.
- **NEVER assume state re-entry is always a fresh start** — Resuming from a stack pop should often bypass "Entry SFX/VFX"; use re-entry flags.

## Implementation — Scripts Are Source of Truth

> **Do NOT** copy inline HierarchicalState / push_state samples. Prior body double-`exit()`ed and ignored resume messages.

**MANDATORY route:**
- Hierarchy / physics-input forward: [hsm_hierarchical_base.gd](scripts/hsm_hierarchical_base.gd)
- Push / pop with `enter({"is_resume": true})`: [hsm_pushdown_stack.gd](scripts/hsm_pushdown_stack.gd)
- Illegal transition blocking: [hsm_transition_guard.gd](scripts/hsm_transition_guard.gd)
- Context payload: [hsm_state_context.gd](scripts/hsm_state_context.gd)

Pushdown contract (from script — single exit, resume msg):

```gdscript
# See hsm_pushdown_stack.gd — do not reimplement
func push_state(state_path: String, msg: Dictionary = {}) -> void: ...
func pop_state() -> void:
    # old.exit(); stack.back().enter({"is_resume": true})
    pass
```

## Expert State Machine Patterns

### 1. HSM Visualizer (Debug Tool)
Use a specialized `Control` node with `_draw()` to visualize the current state stack/hierarchy in the viewport for immediate debugging [3, 11].

```gdscript
class_name HSMVisualizer extends Control
@export var state_machine: Node

func _draw() -> void:
    var font := ThemeDB.fallback_font
    var pos := Vector2(20, 20)
    # Recursively draw active state names...
    draw_string(font, pos, "Active: " + state_machine.current_state.name)
```

### 2. State-Based Audio (Decoupled)
Avoid hardcoding `audio.play()` inside state `enter()` methods. Use a syncer that listens to `state_changed` and maps state names to `AudioStream` resources [12, 13].

```gdscript
class_name StateAudioSyncer extends Node
@export var state_machine: Node
@export var audio_map: Dictionary # { "Jump": preload("jump.wav") }

func _ready() -> void:
    state_machine.state_changed.connect(_on_state_changed)

func _on_state_changed(_old, new_state: Node):
    if audio_map.has(new_state.name):
        $AudioPlayer.stream = audio_map[new_state.name]
        $AudioPlayer.play()
```

### 3. Transition Cost (Utility AI)
Enable states to evaluate their own "weight" based on context. The StateMachine polls sibling costs and transitions to the lowest-cost behavior [17, 18].

```gdscript
# CostState.gd (Base)
func get_cost(context: Dictionary) -> float:
    return 10.0 # Default weight

# UtilityStateMachine.gd
func _physics_process(_d: float) -> void:
    var best_state: Node = current_state
    var low_cost: float = INF
    for child in get_children():
        var cost = child.get_cost(context)
        if cost < low_cost:
            low_cost = cost
            best_state = child
    if best_state != current_state:
        transition_to(best_state.name)
```


## Deep recipes (on demand)

> LLM-ignorance rule: if a general agent would not know it before reading, it lives here or in `scripts/` — never delete, only move.

| Topic | Reference |
|-------|-----------|
| State contract + routing | [hsm-implementation-cookbook.md](references/hsm-implementation-cookbook.md) |

## Reference

> Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.

### Official Documentation
- [Using signals](https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html) — Drive `state_changed` / transition fan-out so listeners (anim, audio, AI) stay decoupled from enter/exit bodies.
- [Scene organization](https://docs.godotengine.org/en/stable/tutorials/best_practices/scene_organization.html) — Child-node state ownership and signal-up / call-down so the machine orchestrates without sibling hard-coupling.
- [What are Godot classes](https://docs.godotengine.org/en/stable/tutorials/best_practices/what_are_godot_classes.html) — Prefer composed state nodes + `class_name` over deep inheritance trees for layered AI behaviors.
- [Idle and Physics Processing](https://docs.godotengine.org/en/stable/tutorials/scripting/idle_and_physics_processing.html) — Why HSMs must forward `_physics_process` / `_process` into the active child (or hierarchy) every tick.
- [Using SceneTree](https://docs.godotengine.org/en/stable/tutorials/scripting/scene_tree.html) — `call_deferred` transitions avoid re-entrant `transition_to()` crashes inside `enter()`.
- [Godot notifications](https://docs.godotengine.org/en/stable/tutorials/best_practices/godot_notifications.html) — Safe wiring timing for initial `enter()` relative to `_ready` and parent caches.
- [Resources](https://docs.godotengine.org/en/stable/tutorials/scripting/resources.html) — Data-driven state definitions (`.tres`) for modular AI without baking scripts into every actor.
- [Using AnimationTree](https://docs.godotengine.org/en/stable/tutorials/animation/animation_tree.html) — Logic-to-AnimationTree travel when gameplay HSM states map to blend/state-machine graphs.
- [AnimationNodeStateMachinePlayback](https://docs.godotengine.org/en/stable/classes/class_animationnodestatemachineplayback.html) — `travel()` / `start()` APIs used by animation syncers tied to HSM state names.
- [Node](https://docs.godotengine.org/en/stable/classes/class_node.html) — Child lookup, process modes, and lifecycle hooks state nodes inherit as scene-tree citizens.
- [InputEvent](https://docs.godotengine.org/en/stable/classes/class_inputevent.html) — Typed events parents forward into `handle_input` on the active state.
- [Timer](https://docs.godotengine.org/en/stable/classes/class_timer.html) — Finite-duration states (stun, dash) via one-shot timers that emit transition signals.

### Related Skills

#### Prerequisites
- [godot-project-foundations](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-project-foundations/SKILL.md) — Scene ownership and project layout conventions every HSM root and child state scene assumes.
- [godot-gdscript-mastery](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-gdscript-mastery/SKILL.md) — class_name, typed Dictionaries/payloads, and Callables needed for guards, deferred transitions, and context objects.
- [godot-signal-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-signal-architecture/SKILL.md) — Signal-up transition events without circular graphs where states emit and also listen to themselves.

#### Complements
- [godot-composition](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-composition/SKILL.md) — Drop HSM / VSM as a StateComponent under a composition root instead of bloating the actor script.
- [godot-input-handling](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-input-handling/SKILL.md) — Sense-layer sampling; states receive directions/actions via handle_input rather than polling globals.
- [godot-characterbody-2d](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-characterbody-2d/SKILL.md) — Locomotion states call move_and_slide / velocity APIs on the actor passed through context.
- [godot-animation-tree-mastery](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-animation-tree-mastery/SKILL.md) — Blend trees and AnimationNodeStateMachine graphs that HSM syncers travel into by state name.
- [godot-resource-data-patterns](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-resource-data-patterns/SKILL.md) — Tunable state Resources (speeds, stun durations, AI weights) separate from runtime Node lifecycle.
- [godot-2d-animation](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-2d-animation/SKILL.md) — Sprite / AnimationPlayer presentation when a lighter sync path than a full AnimationTree is enough.

#### Downstream / consumers
- [godot-combat-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-combat-system/SKILL.md) — Hit-stun, attack windup, and death stacks are classic pushdown / HSM consumers on fighters.
- [godot-ability-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ability-system/SKILL.md) — Cast, channel, and cooldown phases map cleanly to guarded transitions and timed states.
- [godot-turn-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-turn-system/SKILL.md) — Turn phases and interrupt stacks reuse pushdown / concurrent machine orchestration patterns.
- [godot-dialogue-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-dialogue-system/SKILL.md) — Cutscene and dialogue overlays push over gameplay states and must pop without losing context.

#### Master
- [godot-master](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-master/SKILL.md) — Library router and mirrored module entry; open when discovering which Domain Skill owns a cross-cutting architecture concern.

More from thedivergentai/GD-Agentic-Skills

SkillDescription
godot-2d-animationExpert patterns for 2D animation in Godot using AnimatedSprite2D and skeletal cutout rigs. Use when implementing sprite frame animations, procedural animation (squash/stretch), cutout bone hierarchies, or frame-perfect timing systems. Trigger keywords: AnimatedSprite2D, SpriteFrames, animation_finished, animation_looped, frame_changed, frame_progress, set_frame_and_progress, cutout animation, skeletal 2D, Bone2D, procedural animation, animation state machine, advance(0).
godot-2d-physicsExpert patterns for Godot 2D physics including collision layers/masks, Area2D triggers, raycasting, and PhysicsDirectSpaceState2D queries. Use when implementing collision detection, trigger zones, line-of-sight systems, or manual physics queries. Trigger keywords: CollisionShape2D, CollisionPolygon2D, collision_layer, collision_mask, set_collision_layer_value, set_collision_mask_value, Area2D, body_entered, body_exited, RayCast2D, force_raycast_update, PhysicsPointQueryParameters2D, PhysicsShapeQueryParameters2D, direct_space_state, move_and_collide, move_and_slide.
godot-3d-lightingExpert patterns for Godot 3D lighting including DirectionalLight3D shadow cascades, OmniLight3D attenuation, SpotLight3D projectors, VoxelGI vs SDFGI, and LightmapGI baking. Use when implementing realistic 3D lighting, shadow optimization, global illumination, or light probes. Trigger keywords: DirectionalLight3D, OmniLight3D, SpotLight3D, shadow_enabled, directional_shadow_mode, directional_shadow_split, omni_range, omni_attenuation, spot_range, spot_angle, VoxelGI, SDFGI, LightmapGI, ReflectionProbe, Environment, WorldEnvironment.
godot-3d-materialsExpert patterns for Godot 3D PBR materials using StandardMaterial3D including albedo, metallic/roughness workflows, normal maps, ORM texture packing, transparency modes, and shader conversion. Use when creating realistic 3D surfaces, PBR workflows, or material optimization. Trigger keywords: StandardMaterial3D, BaseMaterial3D, albedo_texture, metallic, metallic_texture, roughness, roughness_texture, normal_texture, normal_enabled, orm_texture, transparency, alpha_scissor, alpha_hash, cull_mode, ShaderMaterial, shader parameters.
godot-3d-world-buildingExpert patterns for 3D level design using GridMap with MeshLibrary, CSG constructive solid geometry, occlusion, and runtime GridMap builders. Use when building 3D levels, modular tilesets, or BSP-style geometry. For sky/fog/Environment recipes, route to godot-3d-lighting. Trigger keywords: GridMap, MeshLibrary, set_cell_item, get_cell_item, map_to_local, local_to_map, CSGCombiner3D, CSGBox3D, CSGSphere3D, CSGPolygon3D, OccluderInstance3D, bake CSG.
godot-ability-systemExpert patterns for RPG/action ability systems including cooldown strategies, combo systems, ability chaining, skill trees with prerequisites, upgrade paths, and resource management. Use when implementing unlockable abilities, character progression, or complex skill systems. Trigger keywords: PlayerAbility, AbilityManager, cooldown, SkillTree, SkillNode, prerequisites, can_use, execute, ComboSystem, ability_chain, global_cooldown, charge_system, upgrade_path.
godot-adapt-2d-to-3dExpert patterns for migrating 2D games to 3D including node type conversions, camera systems (third-person, first-person, orbit), physics layer migration, sprite-to-model art pipeline, and control scheme adaptations. Use when porting 2D projects to 3D or adding 3D elements. Trigger keywords: CharacterBody2D to CharacterBody3D, Area2D to Area3D, Camera2D to Camera3D, Vector2 to Vector3, collision_layer migration, sprite to MeshInstance3D, 2D to 3D conversion.
godot-adapt-3d-to-2dExpert patterns for simplifying 3D games to 2D including dimension reduction strategies, 2.5D fake-depth, isometric ports, camera flattening, physics conversion, 3D-to-sprite art pipeline, and control simplification. Use when porting 3D to 2D, building 2.5D / isometric / fake-depth gameplay, creating 2D versions for mobile, or prototyping. Trigger keywords: CharacterBody3D to CharacterBody2D, Camera3D to Camera2D, Vector3 to Vector2, flatten Z-axis, 2.5D, isometric, fake depth, Y-sort, simulated Z, orthogonal projection, 3D to sprite conversion, performance optimization.
godot-adapt-desktop-to-mobileExpert patterns for porting desktop games to mobile including touch control schemes (virtual joystick, gesture detection), UI scaling for small screens, performance optimization for mobile GPUs, battery life management, and platform-specific features. Use when creating mobile ports or cross-platform mobile builds. Trigger keywords: TouchScreenButton, virtual_joystick, gesture_detector, InputEventScreenTouch, InputEventScreenDrag, mobile_optimization, battery_saving, adaptive_performance, MOBILE_ENABLED.
godot-adapt-mobile-to-desktopExpert patterns for scaling mobile games to desktop including mouse/keyboard controls, increased resolution and graphical fidelity, expanded UI layouts, settings menus, window management, and platform-specific features. Use when creating desktop ports or cross-platform releases. Trigger keywords: mouse_controls, keyboard_shortcuts, resolution_scaling, graphics_settings, fullscreen_toggle, window_modes, Steam_integration, desktop_optimization.