学博而后可约,事历而后知要。
零、引言
假设你正在编写玩家角色控制逻辑:当未按下方向键时保持空闲状态,一旦触发方向键输入就切换为移动状态,而按下跳跃键时则执行跳跃动作。这样的代码逻辑该如何实现呢?

一个常规思路是采用多重if-else条件判断结构——对于简单的应用场景,这种实现方式的确可行。但想要在此基础上扩展更多状态(如滑墙、二段跳、翻滚等),问题出现了,多个状态相互耦合,形成了网状结构。代码将不可避免地陷入条件嵌套的泥潭,变得臃肿复杂,难以维护。

为了解决状态间复杂的一对多关联问题,避免状态之间的高度耦合,简化系统结构。故引入了“状态管理器”来封装和协调多个状态之间的转换,从而降低状态间的耦合度,而这就是——“有限状态机”。
一、有限状态机
在引入了“状态管理器”封装一系列状态之间的交互后,从一个状态到另一个状态的转换必须经过状态管理器。当前的结构更加清晰,状态间错综复杂的网状结构得以消解,多个状态间的一对多关系,被转换成状态与状态管理器间的一对一关系。这也符合了迪米特原则: 状态只需知道状态管理器,不需要知道其他状态。

现在,当玩家在空闲状态中按下方向键时,该状态将立即发射包含“目标状态”的上下文。状态管理器接收后,将变更当前状态为目标状态,并执行目标状态的行为。

这使得各状态之间不再需要显式地相互引用,降低了彼此的耦合度,便于增减状态。
二、如何实现
有限状态机的核心由 状态基类(State) 和 状态管理器(StateMachine) 构成,二者通过信号机制实现解耦。
(一)状态基类
作为所有具体状态(如空闲、行走、跳跃等)的抽象基类:
class_name State
extends Node
## 状态基类
## 用于状态模式中表示一个状态,子类应继承此类并实现具体状态逻辑
@warning_ignore("unused_signal")
signal transition # 当前状态发出转换信号
- 进入/退出状态;
# 状态进入时回调
# 当状态到此状态时自动调用,用于初始化状态相关逻辑
func _on_enter() -> void:
pass
# 状态退出时回调
# 当状态机切换出此状态时自动调用,用于清理状态相关资源
func _on_exit() -> void:
pass
- 状态行为逻辑;
# 状态处理函数(每帧调用)
func _on_process(_delta : float) -> void:
pass
# 物理处理函数(固定时间步长调用)
func _on_physics_process(_delta : float) -> void:
pass
- 信号驱动。

最低0.47元/天 解锁文章
953

被折叠的 条评论
为什么被折叠?



