目录
前言
本文章是基于我的另一篇文章做的拓展,关于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面板,按下上下键,就可以进行状态切换了。