zoukankan      html  css  js  c++  java
  • 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();

    状态的切换由具体状态类满足条件自动触发、或者手动触发都可以。

  • 相关阅读:
    PHP无限极分类生成树方法
    如何用c#本地代码实现与Webbrowser中的JavaScript交互
    在sqlite中,如何删除字段? how to drop a column in sqlite
    如何在centos下配置redis开机自启动
    WinForm中的图表控件Chart
    XPath高级用法(冰山一角)
    windows下MySQL的安装(非安装包)
    WinFrom下Webbrowser加载自定义页面的技巧
    .net下使用最小堆实现TopN算法
    .net程序中http请求的超时配置
  • 原文地址:https://www.cnblogs.com/kimmy/p/3738558.html
Copyright © 2011-2022 走看看