| name | godot-state-machine |
| description | Godot 4 有限状态机设计模式,包含状态基类、状态机管理、状态转换和输入处理。 |
Godot 有限状态机设计
概述
有限状态机(FSM)是游戏开发中最常用的设计模式之一,用于管理角色或对象的行为状态。通过将行为拆分为独立的状态类,状态机可以清晰管理状态转换、减少条件判断,使代码结构更加清晰。
1. 状态机核心架构
1.1 状态机管理器
# 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 状态基类
# 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 玩家状态示例
# 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")
# 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")
# 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 层级状态机实现
# 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
# 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 信号通知其他系统 |
| 模板方法 | 基类定义状态接口,子类实现具体行为 |