当前位置: 首页 > news >正文

C# Unity FSM 状态机

C# Unity FSM 状态机

使用状态机可以降低代码耦合性,并且可以优化代码可读性,方便团队协作等。
对于游戏开发内容来讲游戏开发的流程控制玩家动画都可以使用FSM有限状态机来实现。

1.FsmState

每个状态的基类,泛型参数表示所拥有者

public abstract class FsmState<T> where T : class
{protected internal abstract void OnInit(IFsm<T> fsm);protected internal abstract void OnEnter(IFsm<T> fsm);protected internal abstract void OnUpdate(IFsm<T> fsm);protected internal abstract void OnLeave(IFsm<T> fsm);protected internal abstract void OnDestroy(IFsm<T> fsm);protected void ChangeState<TState>(IFsm<T> fsm) where TState : FsmState<T>{Fsm<T> fsmImplement = (Fsm<T>)fsm;if(fsmImplement == null){throw new Exception("FSM is invalid.");}fsmImplement.ChangeState<TState>();}protected void ChangeState(IFsm<T> fsm, Type stateType){Fsm<T> fsmImplement = (Fsm<T>)fsm;if (fsmImplement == null){throw new Exception("FSM is invalid.");}if (stateType == null){throw new Exception("State type is invalid.");}if (!typeof(FsmState<T>).IsAssignableFrom(stateType)){throw new Exception("State type is invalid.");}fsmImplement.ChangeState(stateType);}
}

2.IFsm

有限状态机的接口

public interface IFsm<T> where T : class
{string Name{get;}string FullName{get;}T Owner{get;}int FsmStateCount{get;}bool IsRunning{get;}bool IsDestroyed{get;}FsmState<T> CurrentState{get;}float CurrentStateTime{get;}void Start<TState>() where TState : FsmState<T>;bool HasState<TState>() where TState : FsmState<T>;TState GetState<TState>() where TState : FsmState<T>;FsmState<T> GetState(Type stateType);FsmState<T>[] GetAllStates();
}

3.IFsmManager

有限状态机管理器接口

public interface IFsmManager
{int Count { get; }bool HasFsm<T>() where T : class;bool HasFsm(Type ownerType);bool HasFsm<T>(string name) where T : class;bool HasFsm(Type ownerType, string name);IFsm<T> GetFsm<T>() where T : class;IFsm<T> GetFsm<T>(string name) where T : class;IFsm<T> CreateFsm<T>(T owner, params FsmState<T>[] fsmStates) where T : class;IFsm<T> CreateFsm<T>(string name, T owner, params FsmState<T>[] states) where T : class;IFsm<T> CreateFsm<T>(T owner, List<FsmState<T>> states) where T : class;IFsm<T> CreateFsm<T>(string name, T owner, List<FsmState<T>> states) where T : class;bool DestroyFsm<T>() where T : class;bool DestroyFsm(Type ownerType);bool DestroyFsm<T>(string name) where T : class;bool DestroyFsm(Type ownerType, string name);bool DestroyFsm<T>(IFsm<T> fsm) where T : class;
}

4.FsmBase

有限状态机的基类

public abstract class FsmBase
{private string m_Name;public FsmBase(){m_Name = string.Empty;}public string Name{get{return m_Name;}protected set{m_Name = value ?? string.Empty;}}public string FullName{get{return $"{OwnerType.FullName}.{Name}";}}public abstract Type OwnerType{get;}public abstract int FsmStateCount{get;}public abstract bool IsRunning{get;}public abstract bool IsDestroyed{get;}public abstract string CurrentStateName{get;}public abstract float CurrentStateTime{get;}public abstract void Update();public abstract void Shutdown();
}

5.Fsm

状态机类

public class Fsm<T> : FsmBase, IFsm<T> where T : class
{private T m_Owner;private readonly Dictionary<Type, FsmState<T>> m_States;private FsmState<T> m_CurrentState;private float m_CurrentStateTime;private bool m_IsDestroyed;public Fsm(){m_Owner = null;m_States = new Dictionary<Type, FsmState<T>>();m_CurrentState = null;m_CurrentStateTime = 0f;m_IsDestroyed = true;}public T Owner => m_Owner;public FsmState<T> CurrentState => m_CurrentState;public override Type OwnerType => typeof(T);public override int FsmStateCount => m_States.Count;public override bool IsRunning => m_CurrentState != null;public override bool IsDestroyed => m_IsDestroyed;public override string CurrentStateName => m_CurrentState != null ? m_CurrentState.GetType().FullName : null;public override float CurrentStateTime => m_CurrentStateTime;public static Fsm<T> Create(string name,T owner,params FsmState<T>[] states){if(owner == null){throw new Exception("FSM owner is invalid.");}if(states== null|| states.Length < 1){throw new Exception("FSM states is invalid.");}Fsm<T> fsm = Pool<Fsm<T>>.Rent();fsm.Name = name;fsm.m_Owner = owner;fsm.m_IsDestroyed = false;foreach (FsmState<T> oneState in states){if(oneState == null){throw new Exception("FSM states is invalid.");}Type stateType = oneState.GetType();if (fsm.m_States.ContainsKey(stateType)){throw new Exception($"{stateType} state is already exist");}fsm.m_States.Add(stateType, oneState);oneState.OnInit(fsm);}return fsm;}public static Fsm<T> Create(string name,T owner,List<FsmState<T>> states){if (owner == null){throw new Exception("FSM owner is invalid.");}if (states == null || states.Count < 1){throw new Exception("FSM states is invalid.");}Fsm<T> fsm = Pool<Fsm<T>>.Rent();fsm.Name = name;fsm.m_Owner = owner;fsm.m_IsDestroyed = false;foreach (FsmState<T> oneState in states){if (oneState == null){throw new Exception("FSM states is invalid.");}Type stateType = oneState.GetType();if (fsm.m_States.ContainsKey(stateType)){throw new Exception($"{stateType} state is already exist");}fsm.m_States.Add(stateType, oneState);oneState.OnInit(fsm);}return fsm;}public FsmState<T>[] GetAllStates(){int index = 0;FsmState<T>[] arr = new FsmState<T>[m_States.Count];foreach (FsmState<T> fsmState in m_States.Values){arr[index++] = fsmState;}return arr;}public bool HasState<TState>() where TState : FsmState<T>{return m_States.ContainsKey(typeof(TState));}public override void Shutdown(){Pool<Fsm<T>>.Return(this, (fsm) =>{if(m_CurrentState != null){m_CurrentState.OnLeave(this);}foreach (FsmState<T> oneState in m_States.Values){oneState.OnDestroy(this);}Name = null;m_Owner = null;m_States.Clear();m_CurrentState = null;m_CurrentStateTime = 0f;m_IsDestroyed = true;});}public void Start<TState>() where TState : FsmState<T>{if (IsRunning){throw new Exception("FSM is running, can not start again.");}FsmState<T> state = GetState<TState>();if (state == null){throw new Exception("can not start state");}m_CurrentStateTime = 0f;m_CurrentState = state;m_CurrentState.OnEnter(this);}public void Start(Type stateType){if (IsRunning){throw new Exception("FSM is running, can not start again.");}if (stateType == null){throw new Exception("State type is invalid.");}if (!typeof(FsmState<T>).IsAssignableFrom(stateType)){throw new Exception("State type is invalid.");}FsmState<T> state = GetState(stateType);if (state == null){throw new Exception("FSM can not start state which is not exist.");}m_CurrentStateTime = 0f;m_CurrentState = state;m_CurrentState.OnEnter(this);}public override void Update(){m_CurrentStateTime += Time.deltaTime;m_CurrentState.OnUpdate(this);}public TState GetState<TState>() where TState : FsmState<T>{if (m_States.TryGetValue(typeof(TState), out FsmState<T> fsmState)){return (TState)fsmState;}return null;}public FsmState<T> GetState(Type stateType){if (stateType == null){throw new Exception("State type is invalid.");}if (!typeof(FsmState<T>).IsAssignableFrom(stateType)){throw new Exception("State type is invalid.");}if (m_States.TryGetValue(stateType, out FsmState<T> fsmState)){return fsmState;}return null;}public void ChangeState<TState>(){ChangeState(typeof(TState));}public void ChangeState(Type stateType){if (m_CurrentState == null){throw new Exception("Current state is invalid.");}FsmState<T> state = GetState(stateType);if (state == null){throw new Exception("FSM can not change state which is not exist.");}m_CurrentState.OnLeave(this);m_CurrentStateTime = 0f;m_CurrentState = state;m_CurrentState.OnEnter(this);}
}

6.FsmManager

状态机管理器

public class FsmManager : Singleton<FsmManager>,IFsmManager,IUpdateSingleton
{private readonly Dictionary<string, FsmBase> m_FsmDic;private readonly List<FsmBase> m_TempFsms;public FsmManager(){m_FsmDic = new Dictionary<string, FsmBase>();m_TempFsms = new List<FsmBase>();}public int Count => m_FsmDic.Count;public IFsm<T> CreateFsm<T>(T owner, params FsmState<T>[] fsmStates) where T : class{return CreateFsm(string.Empty, owner, fsmStates);}public IFsm<T> CreateFsm<T>(string name, T owner, params FsmState<T>[] states) where T : class{if (HasFsm<T>(name)){throw new Exception("Already exist FSM");}Fsm<T> fsm = Fsm<T>.Create(name, owner, states);m_FsmDic.Add(fsm.FullName, fsm);return fsm;}public IFsm<T> CreateFsm<T>(T owner, List<FsmState<T>> states) where T : class{return CreateFsm(string.Empty, owner, states);}public IFsm<T> CreateFsm<T>(string name, T owner, List<FsmState<T>> states) where T : class{if (HasFsm<T>(name)){throw new Exception("Already exist FSM");}Fsm<T> fsm = Fsm<T>.Create(name, owner, states);m_FsmDic.Add(fsm.FullName, fsm);return fsm;}public bool DestroyFsm<T>() where T : class{return InternalDestroyFsm($"{typeof(T).FullName}.{string.Empty}");}public bool DestroyFsm(Type ownerType){if (ownerType == null){throw new Exception("Owner type is invalid.");}return InternalDestroyFsm($"{ownerType.FullName}.{string.Empty}");}public bool DestroyFsm<T>(string name) where T : class{return InternalDestroyFsm($"{typeof(T).FullName}.{name}");}public bool DestroyFsm(Type ownerType, string name){if (ownerType == null){throw new Exception("Owner type is invalid.");}return InternalDestroyFsm($"{ownerType.FullName}.{name}");}public bool DestroyFsm<T>(IFsm<T> fsm) where T : class{if (fsm == null){throw new Exception("FSM is invalid.");}return InternalDestroyFsm(fsm.FullName);}public IFsm<T> GetFsm<T>() where T : class{return (IFsm<T>)InternalGetFsm($"{typeof(T).FullName}.{string.Empty}");}public IFsm<T> GetFsm<T>(string name) where T : class{return (IFsm<T>)InternalGetFsm($"{typeof(T).FullName}.{name}");}public bool HasFsm<T>() where T : class{return InternalHasFsm($"{typeof(T).FullName}.{string.Empty}");}public bool HasFsm(Type ownerType){if(ownerType == null){throw new Exception("Owner type is invalid.");}return InternalHasFsm($"{ownerType.FullName}.{string.Empty}");}public bool HasFsm<T>(string name) where T : class{return InternalHasFsm($"{typeof(T).FullName}.{name}");}public bool HasFsm(Type ownerType, string name){if (ownerType == null){throw new Exception("Owner type is invalid.");}return InternalHasFsm($"{ownerType.FullName}.{name}");}private bool InternalDestroyFsm(string name){if(m_FsmDic.TryGetValue(name,out FsmBase fsmBase)){fsmBase.Shutdown();return m_FsmDic.Remove(name);}return false;}private FsmBase InternalGetFsm(string name){FsmBase fsm = null;if (m_FsmDic.TryGetValue(name, out fsm)){return fsm;}return null;}private bool InternalHasFsm(string name){return m_FsmDic.ContainsKey(name);}public void Update(){m_TempFsms.Clear();if (m_FsmDic.Count <= 0)return;foreach (FsmBase fsmBase in m_FsmDic.Values){m_TempFsms.Add(fsmBase);}foreach (FsmBase fsmBase in m_TempFsms){if (fsmBase.IsDestroyed)continue;fsmBase.Update();}}protected override void Load(int assemblyName){}protected override void UnLoad(int assemblyName){}
}

7.测试

(一)IdleState

public class IdleState : FsmState<FsmTest>
{protected internal override void OnDestroy(IFsm<FsmTest> fsm){Debug.Log("销毁 IdleState");}protected internal override void OnEnter(IFsm<FsmTest> fsm){Debug.Log("进入 IdleState");}protected internal override void OnInit(IFsm<FsmTest> fsm){}protected internal override void OnLeave(IFsm<FsmTest> fsm){Debug.Log("离开 IdleState");}protected internal override void OnUpdate(IFsm<FsmTest> fsm){if (Input.GetKeyDown(KeyCode.A)){ChangeState<WalkState>(fsm);}}
}

(二)WalkState

public class WalkState : FsmState<FsmTest>
{protected internal override void OnDestroy(IFsm<FsmTest> fsm){Debug.Log("销毁 WalkState");}protected internal override void OnEnter(IFsm<FsmTest> fsm){Debug.Log("进入 WalkState");}protected internal override void OnInit(IFsm<FsmTest> fsm){}protected internal override void OnLeave(IFsm<FsmTest> fsm){Debug.Log("离开 WalkState");}protected internal override void OnUpdate(IFsm<FsmTest> fsm){if (Input.GetKeyDown(KeyCode.B)){ChangeState<RunState>(fsm);}}
}

(三)RunState

public class RunState : FsmState<FsmTest>
{protected internal override void OnDestroy(IFsm<FsmTest> fsm){Debug.Log("销毁 RunState");}protected internal override void OnEnter(IFsm<FsmTest> fsm){Debug.Log("进入 RunState");}protected internal override void OnInit(IFsm<FsmTest> fsm){}protected internal override void OnLeave(IFsm<FsmTest> fsm){Debug.Log("离开 RunState");}protected internal override void OnUpdate(IFsm<FsmTest> fsm){if (Input.GetKeyDown(KeyCode.C)){ChangeState<IdleState>(fsm);}}
}

mono测试

public class FsmTest : MonoBehaviour
{private IFsm<FsmTest> m_TestFsm;void Start(){SingletonSystem.Initialize();AssemblyManager.Load(1, GetType().Assembly);m_TestFsm = FsmManager.Instance.CreateFsm<FsmTest>("MyTestFsm",this, new IdleState(),new WalkState(),new RunState());m_TestFsm.Start<IdleState>();}void Update(){SingletonSystem.Update();if (Input.GetKeyDown(KeyCode.P)){FsmManager.Instance.DestroyFsm(m_TestFsm);}}
}
http://www.lryc.cn/news/159681.html

相关文章:

  • pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速
  • 【精读Uboot】SPL阶段的board_init_r详细分析
  • canvas绘制渐变色三角形金字塔
  • 企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
  • Debain JDK8 安装
  • Python序列操作指南:列表、字符串和元组的基本用法和操作
  • 【已更新代码图表】2023数学建模国赛E题python代码--黄河水沙监测数据分析
  • 【前端】CSS-Grid网格布局
  • 计算机竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别
  • 2023-9-8 求组合数(二)
  • k8s service的一些特性
  • C++中std::enable_if和SFINAE介绍
  • 华为OD机考算法题:数字加减游戏
  • WPF命令
  • Unity中Shader的屏幕抓取 GrabPass
  • 手撕 队列
  • 【autodl/linux配环境心得:conda/本地配cuda,cudnn及pytorch心得】-未完成
  • macOS Ventura 13.5.2(22G91)发布,附黑/白苹果镜像下载地址
  • vue 子组件向父组件传递参数 子传父
  • 自然语言处理学习笔记(八)———— 准确率
  • Matlab 如何选择窗函数和 FFT 的长度
  • node.js下载安装环境配置以及快速使用
  • 使用栈检查括号的合法性 C 实现
  • 小白备战大厂算法笔试(四)——哈希表
  • 云原生Kubernetes:pod基础
  • Ansys Zemax | 手机镜头设计 - 第 3 部分:使用 STAR 模块和 ZOS-API 进行 STOP 分析
  • CSP-J初赛复习大题整理笔记
  • 面试题 ⑤
  • 硅谷课堂1
  • 第6节-PhotoShop基础课程-认识选区