# 状态机模块 (Framework/FSM) ## 📋 模块概述 通用的有限状态机(FSM)框架,支持状态切换、状态生命周期管理,可用于游戏状态、AI行为、动画控制等场景。 ## 🎯 核心特性 - ✅ 标准状态接口定义 - ✅ 状态基类实现 - ✅ 状态机核心管理 - ✅ 完整的生命周期 - ✅ 状态切换管理 - ✅ 状态更新机制 ## 🗂️ 文件结构 ``` Framework/FSM/ ├── IState.ts # 状态接口 ├── BaseState.ts # 状态基类 └── FSM.ts # 状态机核心 ``` ## 📘 核心类详解 ### IState - 状态接口 **职责**: 定义状态机中状态的标准接口 ```typescript interface IState { // 状态名称(只读) readonly name: string; // 进入状态时调用 onEnter(params?: any): void; // 更新状态(可选,每帧调用) onUpdate?(dt: number): void; // 退出状态时调用 onExit(): void; } ``` ### BaseState - 状态基类 **职责**: 提供状态接口的基础实现 ```typescript abstract class BaseState implements IState { protected _fsm: FSM; // 状态所属的状态机 readonly name: string; // 状态名称 constructor(fsm: FSM, name: string); // 进入状态(可重写) onEnter(params?: any): void { console.log(`[FSM] Enter state: ${this.name}`); } // 更新状态(可重写) onUpdate?(dt: number): void {} // 退出状态(可重写) onExit(): void { console.log(`[FSM] Exit state: ${this.name}`); } } ``` ### FSM - 状态机核心 **职责**: 管理状态的添加、移除和切换 ```typescript class FSM { private _states: Map; // 状态集合 private _currentState: IState | null; // 当前状态 // 添加状态 addState(state: IState): void; // 移除状态 removeState(stateName: string): void; // 切换状态 changeState(stateName: string, params?: any): void; // 获取当前状态 getCurrentState(): IState | null; // 获取当前状态名称 getCurrentStateName(): string | null; // 检查状态是否存在 hasState(stateName: string): boolean; // 获取状态实例 getState(stateName: string): IState | undefined; // 更新状态机(调用当前状态的 onUpdate) update(dt: number): void; // 清空所有状态 clear(): void; } ``` ## 📝 使用指南 ### 1. 定义状态类 ```typescript import { FSM } from './Framework/FSM/FSM'; import { BaseState } from './Framework/FSM/BaseState'; // 待机状态 class IdleState extends BaseState { constructor(fsm: FSM) { super(fsm, "Idle"); } onEnter(params?: any): void { super.onEnter(params); console.log("角色进入待机状态"); } onUpdate(dt: number): void { // 检测输入,切换到移动状态 if (hasInput()) { this._fsm.changeState("Move"); } } } // 移动状态 class MoveState extends BaseState { private _speed: number = 5; constructor(fsm: FSM) { super(fsm, "Move"); } onEnter(params?: any): void { super.onEnter(params); if (params?.speed) { this._speed = params.speed; } console.log(`角色开始移动,速度: ${this._speed}`); } onUpdate(dt: number): void { // 执行移动逻辑 this.move(dt); // 检测停止输入 if (!hasInput()) { this._fsm.changeState("Idle"); } } onExit(): void { super.onExit(); console.log("角色停止移动"); } private move(dt: number): void { // 移动逻辑 } } ``` ### 2. 创建并使用状态机 ```typescript import { FSM } from './Framework/FSM/FSM'; // 1. 创建状态机 const fsm = new FSM(); // 2. 添加状态 fsm.addState(new IdleState(fsm)); fsm.addState(new MoveState(fsm)); fsm.addState(new AttackState(fsm)); // 3. 切换到初始状态 fsm.changeState("Idle"); // 4. 在游戏主循环中更新 function update(dt: number) { fsm.update(dt); } // 5. 切换状态(可传递参数) fsm.changeState("Move", { speed: 10 }); ``` ### 3. 角色 AI 示例 ```typescript // 敌人 AI 状态机 class EnemyAI { private _fsm: FSM; constructor() { this._fsm = new FSM(); // 添加 AI 状态 this._fsm.addState(new PatrolState(this._fsm)); this._fsm.addState(new ChaseState(this._fsm)); this._fsm.addState(new AttackState(this._fsm)); this._fsm.addState(new FleeState(this._fsm)); // 从巡逻状态开始 this._fsm.changeState("Patrol"); } update(dt: number): void { this._fsm.update(dt); } } // 巡逻状态 class PatrolState extends BaseState { onEnter(params?: any): void { super.onEnter(params); console.log("敌人开始巡逻"); } onUpdate(dt: number): void { // 检测玩家 if (detectPlayer()) { this._fsm.changeState("Chase"); } } } // 追击状态 class ChaseState extends BaseState { onEnter(params?: any): void { super.onEnter(params); console.log("敌人发现玩家,开始追击"); } onUpdate(dt: number): void { // 靠近玩家 moveToPlayer(); // 进入攻击范围 if (inAttackRange()) { this._fsm.changeState("Attack"); } // 玩家逃离 else if (!canSeePlayer()) { this._fsm.changeState("Patrol"); } } } ``` ### 4. 动画状态机示例 ```typescript // 角色动画状态机 class CharacterAnimFSM { private _fsm: FSM; private _animator: any; // Cocos 动画组件 constructor(animator: any) { this._animator = animator; this._fsm = new FSM(); // 添加动画状态 this._fsm.addState(new IdleAnimState(this._fsm, this._animator)); this._fsm.addState(new RunAnimState(this._fsm, this._animator)); this._fsm.addState(new JumpAnimState(this._fsm, this._animator)); this._fsm.addState(new AttackAnimState(this._fsm, this._animator)); this._fsm.changeState("Idle"); } // 播放动画 play(animName: string, params?: any): void { this._fsm.changeState(animName, params); } } // 待机动画状态 class IdleAnimState extends BaseState { private _animator: any; constructor(fsm: FSM, animator: any) { super(fsm, "Idle"); this._animator = animator; } onEnter(params?: any): void { super.onEnter(params); this._animator.play("idle"); } } ``` ## 🔄 状态切换流程 ``` changeState("NewState", params) ↓ 1. 检查新状态是否存在 ↓ 2. 如果有当前状态,调用 currentState.onExit() ↓ 3. 切换到新状态 ↓ 4. 调用 newState.onEnter(params) ↓ 5. 更新当前状态引用 ``` ## 📊 状态生命周期 ``` [创建状态实例] ↓ addState(state) - 添加到状态机 ↓ changeState("StateName") - 切换状态 ↓ onEnter(params) - 进入状态 ↓ onUpdate(dt) - 每帧更新(如果实现) ↓ [触发状态切换] ↓ onExit() - 退出状态 ↓ removeState("StateName") - 从状态机移除(可选) ``` ## ⚠️ 注意事项 1. **状态名称唯一**: 每个状态的名称必须唯一,重复添加会覆盖 2. **构造函数传递 FSM**: 状态类的构造函数需要接收 FSM 实例 3. **调用 super**: 重写生命周期方法时,建议先调用 `super.xxx()` 4. **状态切换时机**: 建议在 `onUpdate()` 中判断并切换状态 5. **参数传递**: 切换状态时可以通过 `params` 传递数据 6. **避免循环切换**: 注意状态切换逻辑,避免无限循环 ## 🔍 调试技巧 ### 启用状态日志 ```typescript // BaseState 默认会输出状态切换日志 // [FSM] Enter state: Idle // [FSM] Exit state: Idle ``` ### 获取当前状态信息 ```typescript // 获取当前状态名称 const stateName = fsm.getCurrentStateName(); console.log(`当前状态: ${stateName}`); // 获取当前状态实例 const state = fsm.getCurrentState(); if (state) { console.log(`状态实例: ${state.name}`); } ``` ### 检查状态是否存在 ```typescript if (fsm.hasState("Attack")) { console.log("Attack 状态已添加"); } ``` ## 💡 最佳实践 1. **单一职责**: 每个状态只负责一种行为 2. **状态解耦**: 状态之间通过 FSM 切换,避免直接依赖 3. **参数传递**: 使用 `params` 在状态间传递数据 4. **及时清理**: 不再使用的状态及时移除 5. **文档注释**: 为每个状态类添加清晰的职责说明 ## 📚 应用场景 - ✅ 游戏状态管理(Boot、Login、Game 等) - ✅ 角色状态控制(Idle、Move、Attack 等) - ✅ 敌人 AI 行为(Patrol、Chase、Attack、Flee 等) - ✅ 动画状态机(各种动画之间的切换) - ✅ UI 界面流转(各个界面之间的切换) - ✅ 关卡状态(Ready、Playing、Pause、GameOver 等)