有限状态机/FSM(Finite State Machine)
有限状态机(Finite State Machine, FSM)是一种用于描述对象在不同状态之间转换的模型,广泛应用于游戏开发、嵌入式系统、协议设计等领域。FSM 通过预定义的状态和事件触发机制,控制对象的行为和响应。
🧠 基本概念
概念 | 含义 |
---|---|
状态(State) | 对象在某一时刻的行为特征或行为模式 |
事件(Event/Trigger) | 触发状态变化的外部或内部条件 |
转移(Transition) | 状态之间的切换过程 |
动作(Action) | 在进入某个状态或发生转移时执行的操作 |
🔄 示例:游戏中的角色状态机
一个简单的角色 FSM 可能包含以下内容:
-
状态:
Idle
(空闲)Walking
(行走)Running
(奔跑)Jumping
(跳跃)Attacking
(攻击)
-
事件:
KeyPress.W
KeyPress.Shift
KeyPress.Space
AttackButton
-
转移规则:
Idle + KeyPress.W → Walking
Walking + KeyPress.Shift → Running
Walking + KeyPress.Space → Jumping
Walking + AttackButton → Attacking
-
动作:
- 进入
Walking
时播放行走动画 - 进入
Jumping
时播放跳跃音效 - 进入
Attacking
时触发伤害判定
- 进入
⚙️ FSM 的实现方式
1. 枚举 + 条件判断(简单实现)
ts
enum PlayerState {
Idle,
Walking,
Running,
Jumping,
Attacking
}
let state = PlayerState.Idle;
function onKeyPress(key: string) {
if (state === PlayerState.Idle && key === 'W') {
state = PlayerState.Walking;
playWalkAnimation();
}
}
2. 状态类 + 接口(面向对象实现)
ts
interface State {
onEnter(): void;
onExit(): void;
onUpdate(deltaTime: number): void;
}
class IdleState implements State {
onEnter() { console.log("进入空闲状态"); }
onExit() {}
onUpdate(dt) {}
}
class WalkingState implements State {
onEnter() { playWalkAnimation(); }
onExit() {}
onUpdate(dt) {}
}
class FSM {
private currentState: State;
changeState(newState: State) {
this.currentState.onExit();
this.currentState = newState;
this.currentState.onEnter();
}
update(dt: number) {
this.currentState.onUpdate(dt);
}
}
3. 使用 FSM 库 / 引擎支持
很多游戏引擎(如 Unity、Cocos Creator、Godot)都提供了 FSM 插件或内置状态机系统,例如:
- Unity 的 Animator + StateMachine
- Cocos Creator 的 FSM 插件
- 自定义 FSM 工具库(如 XState)
🎮 FSM 在游戏开发中的典型应用场景
场景 | 使用 FSM 的好处 |
---|---|
玩家角色控制 | 明确状态切换逻辑,避免“if-else”地狱 |
敌人 AI 行为 | 定义巡逻、追击、攻击等状态及其转换条件 |
UI 状态管理 | 控制界面显示、隐藏、过渡动画等 |
游戏流程控制 | 如加载中、主菜单、游戏中、结算等全局状态 |
技能冷却系统 | 管理技能处于可用、冷却、激活等状态 |
✅ FSM 设计建议
建议 | 说明 |
---|---|
清晰划分状态边界 | 每个状态只负责单一职责,避免重叠 |
统一状态变更入口 | 提供统一的 changeState() 方法,便于调试和日志记录 |
支持异步状态切换 | 某些状态可能需要动画或网络请求完成后才切换 |
可视化配置工具 | 使用图形化编辑器定义状态和转移,提升可维护性 |
状态间解耦 | 避免状态直接调用其他状态的方法,通过事件通信 |
🧩 将 FSM 应用于当前项目 GameManager.ts
你当前的游戏管理器可以引入 FSM 来管理以下状态:
状态定义:
ts
enum GameState {
Idle,
Coloring,
Checking,
Success,
NextLevel,
Victory,
Fail
}
状态行为示例:
ts
class ColoringState implements State {
onEnter() {
// 开始颜色调整逻辑
}
onExit() {
// 停止粒子效果
}
}
class SuccessState implements State {
onEnter() {
playSuccessEffect();
scheduleNextState(VictoryState, 3);
}
}
切换逻辑:
ts
if (tolerance < toleranceThreshold) {
fsm.changeState(new SuccessState());
}
📌 总结
特性 | FSM 的优势 |
---|---|
结构清晰 | 明确状态与转换逻辑 |
易于维护 | 新增状态只需扩展,不修改原有逻辑 |
可复用性强 | 可封装为通用模块供多个对象使用 |
便于调试 | 支持状态日志输出、可视化调试 |
如果你希望我帮助你将 GameManager.ts 中的状态逻辑重构为 FSM 模式,我可以进一步提供详细代码结构和实现方案。