学习链接:Unity有限状态机编写 - 木子微冷 - 博客园
实现思路:
1.创建状态基类BasState,所有具体状态类继承该类。基类有3个方法:进入状态、状态中、离开状态;
2.创建管理类来管理状态机(StateMgr),并实现状态机的各个方法:状态转换、设置默认状态等;
3.创建具体状态类(继承BasState),并实现其3个方法(virtual方法如果没有重载override会默认调用父一级的该方法);
4.初始化管理器(StateMgr)。
注意事项:
1.代码实现为C#语言的具体实现,仅供参考,已在Unity上测试运行成功,(修改StateMgr继承的Singleton为MonoBehaviour并运行Init()方法后即可)请放心食用;
2.“StateMgr : Singleton<StateMgr>”管理器类中继承的Singleton是我框架设计的父类,仅仅为了单例实现;
3.StateMgr我为了能一个管理器管理多个不同状态机而改进了下:多了一个字典保存状态机。所以会比学习链接稍微复杂点;
4.为了增强鲁棒性,代码中存在比较多的数据检测,如果移除可以增加可读性。在第一次使用时(Main方法),将StateMgr中的Init()方法调用即可;
5.(可选)string改为Enum枚举类型,对应字典的string部分改为自己设计的Enum,方便后续开发(代码提示)也易于维护(测试开发时是可行的)。存入数据库中需要创建对应表的类,会更复杂些,不过扩展性会更强,效果会比改为枚举类型会更佳,需要增删改状态时可以直接在外部表中修改,并在对应存储数据表的类修改下代码即可。
不足:
1.状态、状态机没有优化好,暂时是直接指定字符串来存储。不方便开发,后续考虑改为枚举类型或者存入数据库中保存;
2.性能可能不是特别好,有待优化。
代码:
BaseState.cs
基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseState
{
public StateMgr stateMgr;
public virtual void OnEnterState() { }
public virtual BaseState OnStayState() { return null; }
public virtual void OnExitState() { }
}
CtrlState.cs
具体行为类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CtrlState : BaseState
{
public StateMgr stateMgr;
public override void OnEnterState()
{
Debug.Log("Enter CtrlState");
}
public override BaseState OnStayState()
{
Debug.Log("Stay CtrlState");
return this;
}
public override void OnExitState()
{
Debug.Log("Exit CtrlState");
}
}
StateMgr.cs
管理器类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 状态机管理器
/// 说明:
/// </summary>
public class StateMgr : Singleton<StateMgr>
{
//管理所有状态机
private Dictionary<string, Dictionary<string, BaseState>> stateDic;
//一个字典保存各个状态机,需要一个枚举
//...
#region 状态机字典集
//当前焦点状态机
private Dictionary<string, BaseState> stateFocusDic;
#endregion
//"当前"状态字典
private Dictionary<string, BaseState> currentState;
//"前一个"状态字典
private Dictionary<string, BaseState> lastState;
public StateMgr()
{
stateDic = new Dictionary<string, Dictionary<string, BaseState>>();
stateFocusDic = new Dictionary<string, BaseState>();
currentState = new Dictionary<string, BaseState>();
lastState = new Dictionary<string, BaseState>();
}
/// <summary>
/// 初始化状态机
/// </summary>
public void Init()
{
//初始注册当前焦点状态机
RegisterStateMachine("stateFocusDic",stateFocusDic);
//初始焦点状态机数据----设计为更便捷的方法?text读取自动初始化?枚举?
RegisterState("stateFocusDic", "none", new NoneState());
RegisterState("stateFocusDic", "ctrl", new CtrlState());
RegisterState("stateFocusDic", "interactive", new InteractiveState());
//设置默认状态
SetDefaultState("stateFocusDic", "