--- name: godot-state-machine description: Godot 4 有限状态机设计模式,包含状态基类、状态机管理、状态转换和输入处理。 --- # Godot 有限状态机设计 ## 概述 有限状态机(FSM)是游戏开发中最常用的设计模式之一,用于管理角色或对象的行为状态。通过将行为拆分为独立的状态类,状态机可以清晰管理状态转换、减少条件判断,使代码结构更加清晰。 ## 1. 状态机核心架构 ### 1.1 状态机管理器 ```gdscript # state_machine.gd class_name StateMachine extends Node signal state_changed(from_state: StringName, to_state: StringName) @export var initial_state: State var current_state: State var states: Dictionary = {} func _ready() -> void: for child in get_children(): if child is State: states[child.name] = child child.state_machine = self child.process_mode = Node.PROCESS_MODE_DISABLED if initial_state: current_state = initial_state current_state.process_mode = Node.PROCESS_MODE_INHERIT current_state.enter() func _process(delta: float) -> void: if current_state: current_state.update(delta) func _physics_process(delta: float) -> void: if current_state: current_state.physics_update(delta) func _unhandled_input(event: InputEvent) -> void: if current_state: current_state.handle_input(event) func transition_to(state_name: StringName, msg: Dictionary = {}) -> void: if not states.has(state_name): push_error("State '%s' not found" % state_name) return var previous_state := current_state previous_state.exit() previous_state.process_mode = Node.PROCESS_MODE_DISABLED current_state = states[state_name] current_state.process_mode = Node.PROCESS_MODE_INHERIT current_state.enter(msg) state_changed.emit(previous_state.name, current_state.name) ``` ### 1.2 状态基类 ```gdscript # state.gd class_name State extends Node var state_machine: StateMachine func enter(_msg: Dictionary = {}) -> 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 ``` ## 2. 具体状态实现 ### 2.1 玩家状态示例 ```gdscript # player_idle.gd class_name PlayerIdle extends State @export var player: Player func enter(_msg: Dictionary = {}) -> void: player.animation.play("idle") func physics_update(_delta: float) -> void: var direction := Input.get_vector("left", "right", "up", "down") if direction != Vector2.ZERO: state_machine.transition_to("Move") func handle_input(event: InputEvent) -> void: if event.is_action_pressed("attack"): state_machine.transition_to("Attack") elif event.is_action_pressed("jump"): state_machine.transition_to("Jump") ``` ```gdscript # player_move.gd class_name PlayerMove extends State @export var player: Player func enter(_msg: Dictionary = {}) -> void: player.animation.play("walk") func physics_update(_delta: float) -> void: var direction := Input.get_vector("left", "right", "up", "down") if direction == Vector2.ZERO: state_machine.transition_to("Idle") elif Input.is_action_just_pressed("attack"): state_machine.transition_to("Attack") ``` ```gdscript # player_attack.gd class_name PlayerAttack extends State @export var player: Player var attack_cooldown: float = 0.3 var attack_timer: float = 0.0 func enter(_msg: Dictionary = {}) -> void: player.animation.play("attack") attack_timer = attack_cooldown func physics_update(_delta: float) -> void: attack_timer -= _delta if attack_timer <= 0 and player.animation.current_animation == "attack": state_machine.transition_to("Idle") ``` ## 3. 层级状态机 ### 3.1 层级状态机实现 ```gdscript # hierarchical_state_machine.gd class_name HierarchicalStateMachine extends StateMachine var parent_state: State func init(parent: State) -> void: parent_state = parent for child in get_children(): if child is State: child.state_machine = self ``` ```gdscript # state_with_substates.gd class_name StateWithSubstates extends State @onready var hierarchical_fsm := HierarchicalStateMachine.new() func enter(_msg: Dictionary = {}) -> void: hierarchical_fsm.init(self) add_child(hierarchical_fsm) hierarchical_fsm._ready() func exit() -> void: hierarchical_fsm.current_state.exit() hierarchical_fsm.queue_free() ``` ## 4. 状态模式选择 | 模式 | 适用场景 | 复杂度 | |------|----------|--------| | **简单状态机** | 状态较少、无嵌套 | 低 | | **层级状态机** | 状态有共性、需要共享逻辑 | 中 | | **下推自动机** | 状态需要堆栈管理(如战斗/逃跑) | 高 | ## 5. 设计模式总结 | 模式 | 应用场景 | |------|----------| | **状态模式** | 将每个状态封装为独立类 | | **观察者模式** | `state_changed` 信号通知其他系统 | | **模板方法** | 基类定义状态接口,子类实现具体行为 |