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();

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

  • 相关阅读:
    多个类定义attr属性重复的问题:Attribute "xxx" has already been defined
    好用的批量改名工具——文件批量改名工具V2.0 绿色版
    得到ImageView中drawable显示的区域的计算方法
    得到view坐标的各种方法
    实现类似于QQ空间相册的点击图片放大,再点后缩小回原来位置
    Material Designer的低版本兼容实现(五)—— ActivityOptionsCompat
    Android 自带图标库 android.R.drawable
    解决 Attempting to destroy the window while drawing!
    解决Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 4
    Material Designer的低版本兼容实现(四)—— ToolBar
  • 原文地址:https://www.cnblogs.com/kimmy/p/3738558.html
Copyright © 2011-2022 走看看