通俗点讲,有限状态机是:将对象的状态(攻击、闲置、晕眩)的实现代码,提取出来,封装成状态。由状态机负责在各个状态之间调度。
对象持有状态管理类(状态机)的引用,与具体的状态解耦。
OK,那接下来开始设计一个塔的状态,我们有一个父类FiniteState,状态机只和父类交互,屏蔽了状态具体实现
using System.Collections.Generic; /// <summary> /// 塔的状态机工具类 /// </summary> public class TowerStateHelper { /// <summary> /// 状态个数 /// </summary> private const int STATE_COUNT = 4; /// <summary> /// 创建状态集合 /// </summary> /// <param name="tower">作用对象</param> /// <returns></returns> public static Dictionary<StateType, FiniteState> GenerateStateList(TowerBase tower) { Dictionary<StateType, FiniteState> stateList = new Dictionary<StateType, FiniteState>(STATE_COUNT); stateList.Add(StateType.Idle, new StateIdle() { TargetTower = tower, StateTypeId = StateType.Idle }); stateList.Add(StateType.Guard, new StateGuard() { TargetTower = tower, StateTypeId = StateType.Guard }); stateList.Add(StateType.Attack, new StateAttack() { TargetTower = tower, StateTypeId = StateType.Attack }); stateList.Add(StateType.Spell, new StateSpell() { TargetTower = tower, StateTypeId = StateType.Spell }); return stateList; } } /// <summary> /// 状态类型 /// </summary> public enum StateType { /// <summary> /// 不可用 /// </summary> Innit, /// <summary> /// 闲置 /// </summary> Idle, /// <summary> /// 攻击 /// </summary> Attack, /// <summary> /// 警惕 /// </summary> Guard, /// <summary> /// 吟唱 /// </summary> Spell }
using System.Collections.Generic; /// <summary> /// 状态机 /// </summary> public class TowerStateMachine { #region 公共属性 /// <summary> /// 追溯前面的状态 /// </summary> public StateType PreviousStateType { get; set; } #endregion #region 私有属性 /// <summary> /// 全局状态 /// </summary> private FiniteState _globalState; /// <summary> /// 当前状态 /// </summary> private FiniteState _currentState; /// <summary> /// 状态列表 /// </summary> private Dictionary<StateType, FiniteState> _stateList; #endregion #region 重写事件 /// <summary> /// 初始化方法 /// </summary> /// <param name="globalState">全局状态</param> /// <param name="newStateType">当前状态</param> public TowerStateMachine(TowerBase tower, FiniteState globalState, StateType newStateType) { PreviousStateType= StateType.Innit; _stateList = TowerStateHelper.GenerateStateList(tower); if (null != globalState) { globalState.OnEnter(); _globalState = globalState; } _stateList[newStateType].OnEnter(); _currentState = _stateList[newStateType]; } #endregion #region 公共方法 /// <summary> /// 执行 /// </summary> public void Excute() { if (null != _globalState) _globalState.OnExcute(); if (null != _currentState) _currentState.OnExcute(); } /// <summary> /// 改变状态 /// </summary> /// <param name="newStateType"></param> public void ChangeStatus(StateType newStateType) { if (newStateType == _currentState.StateTypeId) return; PreviousStateType = _currentState.StateTypeId; _currentState.OnExit(); _stateList[newStateType].OnEnter(); _currentState = _stateList[newStateType]; } #endregion }
/// <summary> /// 状态基类 /// </summary> public abstract class FiniteState { /// <summary> /// 状态机类型 /// </summary> public StateType StateTypeId { get; set; } /// <summary> /// 塔对象 /// </summary> public TowerBase TargetTower { get; set; } /// <summary> /// 进入 /// </summary> public abstract void OnEnter(); /// <summary> /// 执行 /// </summary> public abstract void OnExcute(); /// <summary> /// 退出 /// </summary> public abstract void OnExit(); }
//声明 private TowerStateMachine _stateMachine; //初始化 _stateMachine = new TowerStateMachine(this, null, StateType.Idle); //在Update方法里调用 _stateMachine.Excute();
状态的切换由具体状态类满足条件自动触发、或者手动触发都可以。