用途
本技能包为 Godot 引擎提供分层有限状态机(HSM)与下推自动机的专家级实现蓝图,面向复杂 AI 与角色行为。当基础 FSM 无法满足需求,或需要实现分层 AI 时使用。关键词包括状态机、HSM、分层、下推自动机、状态栈、FSM、AI 行为。
主要能力
技能包提供以下脚本:
- hsm_hierarchical_base.gd:高级 HSM 基类委托器,用于将物理和输入传播到子状态。
- hsm_pushdown_stack.gd:专业下推自动机,用于中断性状态(暂停/菜单)的堆叠。
- hsm_state_context.gd:解耦的上下文对象模式,用于在状态之间传递持久数据。
- hsm_transition_guard.gd:专家级转移校验逻辑,防止非法状态变更。
- hsm_animation_syncer.gd:自动化的逻辑到 AnimationTree 同步,带基于状态的 travel 逻辑。
- hsm_concurrent_logic.gd:并行状态机(例如移动 + 攻击)的编排。
- hsm_resource_state_loader.gd:使用自定义 Godot 资源(.tres)的数据驱动状态定义。
- hsm_reentry_aware_state.gd:处理从栈恢复的逻辑与全新进入事件。
- hsm_state_history_logger.gd:用于追踪状态转移历史和栈深度的调试环形缓冲区。
- hsm_state_timer_component.gd:用于有限状态(如眩晕或冲刺)的自动转移组件。
使用方式
技能包提供决策树帮助选择机器类型:
- 少量互斥状态、无嵌套:扁平 FSM,使用 hsm_logic_state.gd 加薄父节点。
- 嵌套子状态(移动/空中/攻击子级):HSM,使用 hsm_hierarchical_base.gd。
- 中断覆盖层(眩晕/菜单/对话)后恢复:下推,使用 hsm_pushdown_stack.gd 加 hsm_reentry_aware_state.gd。
- 并行关注点(移动 + 武器):并发,使用 hsm_concurrent_logic.gd。
- 每 tick 按分数选择最佳动作:效用成本轮询,使用专家模式第 3 节加 hsm_transition_guard.gd。
对于层级/下推/守卫,必须阅读 hsm_hierarchical_base.gd、hsm_pushdown_stack.gd、hsm_transition_guard.gd(以及用于叶子行为的 hsm_logic_state.gd)。
下推契约(来自脚本,单一 exit,恢复消息):
# 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
专家状态规则(禁止事项)
层级与委托:
- 绝不要忘记将物理/输入传播到子级——在 HSM 中,未从父级 _physics_process 调用 child.physics_update() 会使子逻辑孤立。
- 绝不要使用超过 3 层的深层嵌套——极端层级会造成“状态意大利面”。如果逻辑如此复杂,考虑行为树或效用 AI。
转移与生命周期:
- 绝不要在未先调用 exit() 的情况下调用 enter()——跳过 exit 逻辑会让计时器、补间或音频循环在后台继续运行,导致资源泄漏。
- 绝不要在转移帧修改状态——在 enter() 内部重入调用 transition_to() 会导致递归崩溃。如果需要立即子转移,使用 call_deferred。
- 绝不要将状态名硬编码为字符串——像 transition_to("Idel") 这样的拼写错误是静默杀手。使用基于 class_name 的检查或常量。
架构与上下文:
- 绝不要为状态数据使用全局单例——将状态耦合到 GameManager.player_health 会使它们无法复用。传递 Context 对象。
- 绝不要无限推入状态——在下推自动机中,每次 push_state 都必须有退役计划(pop_state)以避免栈溢出。
- 绝不要假设状态重入总是全新开始——从栈弹出恢复通常应绕过“进入音效/特效”;使用重入标志。
专家状态机模式
- HSM 可视化器(调试工具):使用专门的 Control 节点配合 _draw() 在视口中可视化当前状态栈/层级,便于即时调试。
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)
- 基于状态的音频(解耦):避免在状态 enter() 方法中硬编码 audio.play()。使用监听 state_changed 的同步器,将状态名映射到 AudioStream 资源。
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()
- 转移成本(效用 AI):让状态基于上下文评估自身“权重”。状态机轮询兄弟成本并转移到最低成本行为。
# 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)
深度配方(按需)
状态契约与路由:hsm-implementation-cookbook.md。
适用场景
- 需要嵌套子状态的角色行为(移动/空中/攻击子级)。
- 需要中断覆盖层(眩晕/菜单/对话)后恢复的场景。
- 需要并行关注点(移动 + 武器)的场景。
- 需要每 tick 按分数选择最佳动作的效用 AI。
- 下游消费者包括战斗系统(受击硬直、攻击前摇、死亡栈)、能力系统(施法、引导、冷却阶段)、回合系统(回合阶段和中断栈)、对话系统(过场和对话覆盖层)。
限制
- 绝不要使用超过 3 层的深层嵌套,否则会造成“状态意大利面”,此时应考虑行为树或效用 AI。
- 绝不要为状态数据使用全局单例,否则状态无法复用。
- 绝不要无限推入状态,每次 push_state 都必须有 pop_state 以避免栈溢出。
- 绝不要在未先调用 exit() 的情况下调用 enter(),否则会导致资源泄漏。
- 绝不要在转移帧修改状态,否则会导致递归崩溃。
- 绝不要将状态名硬编码为字符串,应使用 class_name 检查或常量。
前置与相关技能
前置:godot-project-foundations、godot-gdscript-mastery、godot-signal-architecture。
补充:godot-composition、godot-input-handling、godot-characterbody-2d、godot-animation-tree-mastery、godot-resource-data-patterns、godot-2d-animation。
下游消费者:godot-combat-system、godot-ability-system、godot-turn-system、godot-dialogue-system。
主技能:godot-master。
官方文档参考
技能包列出 Godot 官方文档链接,涵盖信号、场景组织、Godot 类、空闲与物理处理、SceneTree、Godot 通知、资源、AnimationTree、AnimationNodeStateMachinePlayback、Node、InputEvent、Timer 等主题。建议仅在研究特定 API 时打开官方文档链接,路由到对等领域时加载相关技能,不要预加载整个网格。