首页 > 代码库 > Unity状态机的实现,以《塔防》为例
Unity状态机的实现,以《塔防》为例
什么是有限状态机?
通俗点讲,有限状态机是:将对象的状态(攻击、闲置、晕眩)的实现代码,提取出来,封装成状态。由状态机负责在各个状态之间调度。
对象持有状态管理类(状态机)的引用,与具体的状态解耦。
OK,那接下来开始设计一个塔的状态,我们有一个父类FiniteState,状态机只和父类交互,屏蔽了状态具体实现
塔与状态是一对一的关系,也就是说,在塔创建的时候,全部状态已经生成好了(GenerateStateList方法), 我们根据状态的枚举类进行切换。
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 }
状态基类,我们定义了进入、OnExcute(每次update被调用)、退出方法
/// <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();
状态的切换由具体状态类满足条件自动触发、或者手动触发都可以。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。