Unity学习笔记--FSM有限状态机的实现

前言

本文章是基于我的另一篇文章做的拓展,关于FSM的概念和状态模式大家有兴趣的可以看看。我这里就直接上源码了。文章最后会给出工程地址。
浅谈设计模式和其Unity中的应用:四、状态模式

具体实现

步骤一:列举出所有的状态和转换条件

namespace M_FSM
{
    
    
    /// <summary>
    /// 状态转换条件枚举
    /// </summary>
    public enum Transition
    {
    
    
        NullTransition,
        UpArrow,
        DownArrow,
    }
    /// <summary>
    /// 状态枚举
    /// </summary>
    public enum StateID
    {
    
    
        Null,
        Stand,//站立
        Jump,//跳跃
        Crouch,//下蹲
    }
}

步骤二:创建所有状态的基类

namespace M_FSM
{
    
    
    public abstract class M_FSMState
    {
    
    
        protected M_FSMSystem fSM;
        protected Transform ower;
        protected Dictionary<Transition, StateID> dic;
        public StateID stateID {
    
     get; protected set; }
        /// <summary>
        /// 进入状态时调用
        /// </summary>
        public abstract void OnEnter();
        /// /// <summary>
        /// 状态持续时调用(当前状态执行的逻辑放在这里)
        /// </summary>
        public abstract void OnUpdate();
        /// <summary>
        /// 状态持续时调用(状态转换条件判断放在这里)
        /// </summary>
        public abstract void OnReason();
        /// <summary>
        /// 退出状态时调用
        /// </summary>
        public abstract void OnExit();
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="_fSM">FSM管理者</param>
        /// <param name="_stateID">当前状态ID</param>
        /// <param name="_ower">当前状态属于哪一个对象</param>
        public M_FSMState(M_FSMSystem _fSM, StateID _stateID, Transform _ower)
        {
    
    
            fSM = _fSM;
            stateID = _stateID;
            ower = _ower;
            dic = new Dictionary<Transition, StateID>();
        }
        /// <summary>
        /// 增加过渡条件
        /// </summary>
        /// <param name="transition">过渡条件</param>
        /// <param name="nextStateID">下一个状态</param>
        public bool AddTransition(Transition transition, StateID nextStateID)
        {
    
    
            if (transition == Transition.NullTransition || dic.ContainsKey(transition))
            {
    
    
                return false;
            }
            dic.Add(transition, nextStateID);
            return true;
        }
        /// <summary>
        /// 删除过渡条件
        /// </summary>
        /// <param name="transition">过渡条件</param>
        public bool DeleteTransition(Transition transition)
        {
    
    
            if (transition == Transition.NullTransition || !dic.ContainsKey(transition))
            {
    
    
                return false;
            }
            dic.Remove(transition);
            return true;
        }
        /// <summary>
        /// 获取过渡条件指向的下一个状态
        /// </summary>
        /// <param name="transition">过渡条件</param>
        /// <returns>下一个状态</returns>
        public StateID GetNextState(Transition transition)
        {
    
    
            if (transition == Transition.NullTransition || !dic.ContainsKey(transition))
            {
    
    
                return StateID.Null;
            }
            return dic[transition];
        }
    }
}

步骤三:创建所有状态的管理者

namespace M_FSM
{
    
    
    public class M_FSMSystem
    {
    
    
        private Dictionary<StateID, M_FSMState> dic = new Dictionary<StateID, M_FSMState>();
        private M_FSMState currentState;
        public void Update()
        {
    
    
            currentState?.OnUpdate();
            currentState?.OnReason();
        }
        /// <summary>
        /// 添加状态
        /// </summary>
        /// <param name="state">添加的状态</param>
        /// <returns>是否添加成功</returns>
        public bool AddState(M_FSMState state)
        {
    
    
            if (state == null || state.stateID == StateID.Null || dic.ContainsKey(state.stateID))
            {
    
    
                return false;
            }
            dic.Add(state.stateID, state);
            return true;
        }
        /// <summary>
        /// 删除状态
        /// </summary>
        /// <param name="state">删除的状态</param>
        /// <returns>是否删除成功</returns>
        public bool DeleteState(M_FSMState state)
        {
    
    
            if(state == null)
            {
    
    
                return false;
            }
            return DeleteState(state.stateID);
        }
        /// <summary>
        /// 删除状态
        /// </summary>
        /// <param name="stateID">删除的状态</param>
        /// <returns>是否删除成功</returns>
        public bool DeleteState(StateID stateID)
        {
    
    
            if (stateID == StateID.Null || !dic.ContainsKey(stateID))
            {
    
    
                return false;
            }
            dic.Remove(stateID);
            return true;
        }
        /// <summary>
        /// 转换到下一个状态
        /// </summary>
        /// <param name="transition"></param>
        /// <returns>是否转换成功</returns>
        public bool TransitionState(Transition transition)
        {
    
    
            StateID nextStateID = StateID.Null;
            if(transition == Transition.NullTransition || (nextStateID = currentState.GetNextState(transition)) == StateID.Null || !dic.ContainsKey(nextStateID) || currentState == null)
            {
    
    
                return false;
            }
            currentState.OnExit();
            currentState = dic[nextStateID];
            currentState.OnEnter();
            return true;
        }
        /// <summary>
        /// 设置FSM启动时第一个状态
        /// </summary>
        /// <param name="state">默认第一个状态</param>
        /// <returns>是否设置成功</returns>
        public bool SetNormalState(M_FSMState state)
        {
    
    
            if(state == null || state.stateID == StateID.Null || !dic.ContainsKey(state.stateID))
            {
    
    
                return false;
            }
            currentState = state;
            return true;
        }
    }
}

步骤四:添加不同状态

站立状态:Stand

namespace M_FSM
{
    
    
    public class M_StandState : M_FSMState
    {
    
    
        public M_StandState(M_FSMSystem _fSM, Transform _ower) : base(_fSM, StateID.Stand, _ower) {
    
     }

        public override void OnEnter() {
    
     }

        public override void OnExit() {
    
     }

        public override void OnReason()
        {
    
    
            if (Input.GetKeyDown(KeyCode.UpArrow))
            {
    
    
                fSM.TransitionState(Transition.UpArrow);
            }
            if (Input.GetKeyDown(KeyCode.DownArrow))
            {
    
    
                fSM.TransitionState(Transition.DownArrow);
            }
        }

        public override void OnUpdate()
        {
    
    
            Debug.Log("Stand");
        }
    }
}

跳跃状态:Jump

namespace M_FSM
{
    
    
    public class M_JumpState : M_FSMState
    {
    
    
        public M_JumpState(M_FSMSystem _fSM, Transform _ower) : base(_fSM, StateID.Jump, _ower) {
    
     }

        public override void OnEnter() {
    
     }

        public override void OnExit() {
    
     }

        public override void OnReason()
        {
    
    
            if (Input.GetKeyDown(KeyCode.DownArrow))
            {
    
    
                fSM.TransitionState(Transition.DownArrow);
            }
        }

        public override void OnUpdate()
        {
    
    
            Debug.Log("Jump");
        }
    }
}

下蹲状态:Crouch

namespace M_FSM
{
    
    
    public class M_CrouchState : M_FSMState
    {
    
    
        public M_CrouchState(M_FSMSystem _fSM, Transform _ower) : base(_fSM, StateID.Crouch, _ower) {
    
     }

        public override void OnEnter() {
    
     }

        public override void OnExit() {
    
     }

        public override void OnReason()
        {
    
    
            if (Input.GetKeyDown(KeyCode.UpArrow))
            {
    
    
                fSM.TransitionState(Transition.UpArrow);
            }
        }

        public override void OnUpdate()
        {
    
    
            Debug.Log("Crouch");
        }
    }
}

步骤四:创建玩家控制器

using UnityEngine;
using M_FSM;

public class PlayerController : MonoBehaviour
{
    
    
    private M_FSMSystem m_fsm;
    
    private void Awake()
    {
    
    
        m_fsm = new M_FSMSystem();

        M_FSMState standState = new M_StandState(m_fsm, transform);
        standState.AddTransition(Transition.UpArrow, StateID.Jump);
        standState.AddTransition(Transition.DownArrow, StateID.Crouch);

        M_FSMState crouchState = new M_CrouchState(m_fsm, transform);
        crouchState.AddTransition(Transition.UpArrow, StateID.Stand);

        M_FSMState jumpState = new M_JumpState(m_fsm, transform);
        jumpState.AddTransition(Transition.DownArrow, StateID.Stand);

        m_fsm.AddState(standState);
        m_fsm.AddState(crouchState);
        m_fsm.AddState(jumpState);

        m_fsm.SetNormalState(standState);
    }
    private void Update()
    {
    
    
        m_fsm.Update();
    }
}

步骤四:运行

给玩家挂上PlayrController运行就可以了。
可以试试打开Console面板,按下上下键,就可以进行状态切换了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源码工程

FSM有限状态机源码


要更努力地成为一名优秀的游戏开发者!

猜你喜欢

转载自blog.csdn.net/qq_52855744/article/details/122320549
今日推荐