Unity状态机(含多线程处理)

众所周知,Unity在开发游戏的时候经常用到状态机,而通常情况下,我们会使用简单的枚举类型设置状态,然后通过调整枚举,来切换状态,在简单情况下是可以的,就像是Unity中Animator切换动画状态就是,直接通过动画片段的名称切换。而当状态很多的时候,直接切换就显得有些很不安全,而且友好性也不是很好,所以根据Unity中Animator这种通过条件切换状态的架构,我写了一个简单的状态机,给大家分享。
  • 外部委托定义
    [AppleScript]  纯文本查看  复制代码
      /// <summary>
      /// 状态内部事件委托
      /// </summary>
      public delegate void StateFunctionEventHandler();
      /// <summary>
      /// 状态条件判断委托
      /// </summary>
      public delegate bool StateTranslateEventHandler();
  • 状态类
    [AppleScript]  纯文本查看  复制代码
      /// <summary>
      /// 状态类
      /// </summary>
      public class State {
          /// <summary>
          /// 状态内部事件
          /// </summary>
          public event StateFunctionEventHandler stateFunc;
          /// <summary>
          /// 状态转换事件<目标状态,切换条件>
          /// </summary>
          public Dictionary<State,StateTranslateEventHandler> stateTrs;
    
          /// <summary>
          /// 状态名称
          /// </summary>
          /// <value>The name of the state.</value>
          public string stateName{get;private set;}
    
          /// <summary>
          /// 状态运行中
          /// </summary>
          public bool isRun = false;
    
          /// <summary>
          /// 状态内部事件执行间隔时间(毫秒)
          /// </summary>
          /// <value>The state function delta time.</value>
          public int stateFunctionDeltaTime{private get; set;}
          /// <summary>
          /// 状态构造
          /// </summary>
          /// <param name="name">Name.</param>
          public State(string name)
          {
              stateName = name;
              stateTrs = new Dictionary<State, StateTranslateEventHandler> ();
              stateFunctionDeltaTime = 200;
              Thread th = new Thread (Update);
              th.Start ();
          }
    
          /// <summary>
          /// 状态内部事件执行
          /// </summary>
          public void Update()
          {
              while(true)
              {
                  if(!isRun)
                  {
                      continue;
                  }
    
                  Thread.Sleep (stateFunctionDeltaTime);
                  if(stateFunc != null)
                  {
                      stateFunc();
                  }
              }
          }
          /// <summary>
          /// 注册切换事件.
          /// </summary>
          /// <param name="target">目标状态.</param>
          /// <param name="conditional">条件事件.</param>
          public void RegisterTranslate(State target, StateTranslateEventHandler conditional)
          {
              try
              {
                  stateTrs.Add (target, conditional);
              }
              catch(Exception ex)
              {
                  Debug.LogError(ex.ToString());
              }
          }
      }
  • 状态管理类
    [AppleScript]  纯文本查看  复制代码
      /// <summary>
      /// 状态管理
      /// </summary>
      public class StateController : State {
    
          /// <summary>
          /// 状态管理构造
          /// </summary>
          /// <param name="name">Name.</param>
          public StateController(string name) : base(name)
          {
              states = new Dictionary<string, State> ();
              stateparams = new Dictionary<string, object> ();
              stateFunc += CheckTranslate;
              isRun = true;
              Thread mainTh = new Thread (Update);
              mainTh.Start ();
          }
          /// <summary>
          /// 状态字典
          /// </summary>
          Dictionary<string,State> states;
          /// <summary>
          /// 状态切换参数字典
          /// </summary>
          Dictionary<string,object> stateparams;
          /// <summary>
          /// 当前状态
          /// </summary>
          public State currentState;
          /// <summary>
          /// 添加状态
          /// </summary>
          /// <returns>The state.</returns>
          /// <param name="statename">状态名称.</param>
          public State AddState(string statename)
          {
              State temp = new State (statename);
              states.Add (statename, temp);
              SetDefault (temp);
              return temp;
          }
          /// <summary>
          /// 添加状态
          /// </summary>
          /// <param name="s">状态.</param>
          public void AddState(State s)
          {
              states.Add (s.stateName, s);
              SetDefault (s);
          }
          /// <summary>
          /// 移除状态
          /// </summary>
          /// <param name="statename">状态名称.</param>
          public void RemoveState(string statename)
          {
              states.Remove (statename);
          }
          /// <summary>
          /// 设置默认状态
          /// </summary>
          /// <param name="s">S.</param>
          private void SetDefault (State s)
          {
              if(states.Count == 1)
              {
                  currentState = s;
                  s.isRun = true;
              }
          }
          /// <summary>
          /// 切换状态
          /// </summary>
          /// <param name="name">状态名称.</param>
          public void TranslateState(string name)
          {
              if(states[name] != null)
              {
                  currentState.isRun = false;
                  currentState = states [name];
                  states [name].isRun = true;
              }
          }
          /// <summary>
          /// 获取状态
          /// </summary>
          /// <returns>The state.</returns>
          /// <param name="statename">Statename.</param>
          public State GetState(string statename)
          {
              return states [statename];
          }
    
          /// <summary>
          /// 注册参数
          /// </summary>
          /// <param name="paramName">参数名称.</param>
          /// <param name="value">参数值.</param>
          public void RegisterParams(string paramName, int value)
          {
              stateparams.Add (paramName, value);
          }
          /// <summary>
          /// 注册参数
          /// </summary>
          /// <param name="paramName">参数名称.</param>
          /// <param name="value">参数值.</param>
          public void RegisterParams(string paramName, float value)
          {
              stateparams.Add (paramName, value);
          }
          /// <summary>
          /// 注册参数
          /// </summary>
          /// <param name="paramName">参数名称.</param>
          /// <param name="value">参数值.</param>
          public void RegisterParams(string paramName, string value)
          {
              stateparams.Add (paramName, value);
          }
          /// <summary>
          /// 获取int类型参数
          /// </summary>
          /// <returns>The int parameters.</returns>
          /// <param name="paraName">Para name.</param>
          public int GetIntParams(string paraName)
          {
              return (int)stateparams [paraName];
          }
          /// <summary>
          /// 获取float类型参数
          /// </summary>
          /// <returns>The float parameters.</returns>
          /// <param name="paraName">Para name.</param>
          public float GetFloatParams(string paraName)
          {
              return (float)stateparams [paraName];
          }
          /// <summary>
          /// 获取string类型参数
          /// </summary>
          /// <returns>The string parameters.</returns>
          /// <param name="paraName">Para name.</param>
          public string GetStringParams(string paraName)
          {
              return (string)stateparams [paraName];
          }
          /// <summary>
          /// 设置int参数
          /// </summary>
          /// <param name="paraName">Para name.</param>
          /// <param name="value">Value.</param>
          public void SetIntParams(string paraName, int value)
          {
              stateparams[paraName] =value;
          }
          /// <summary>
          /// 设置float参数
          /// </summary>
          /// <param name="paraName">Para name.</param>
          /// <param name="value">Value.</param>
          public void SetFloatParams(string paraName, float value)
          {
              stateparams[paraName] =value;
          }
          /// <summary>
          /// 设置string参数
          /// </summary>
          /// <param name="paraName">Para name.</param>
          /// <param name="value">Value.</param>
          public void SetStringParams(string paraName, string value)
          {
              stateparams[paraName] =value;
          }
          /// <summary>
          /// 检查状态切换
          /// </summary>
          private void CheckTranslate()
          {
              foreach (var item in currentState.stateTrs) 
              {
                  if(item.Value())
                  {
                      TranslateState(item.Key.stateName);
                  }
              }
          }
      }
  • 实例应用
    [AppleScript]  纯文本查看  复制代码
    public class GameController : MonoBehaviour {
    
      //单例
      static StateController stateController;
      //外部测试
      public bool test = false;
    
      void Awake()
      {
          //1、实例化单例
          stateController = new StateController ("MainSc");
      }
    
      void Start()
      {
          //2、注册状态Idle
          State idle = stateController.AddState ("Idle");
          //2、注册状态Run
          State run = stateController.AddState ("Run");
          //3、注册参数Speed,默认值0
          stateController.RegisterParams ("Speed", 0f);
          //4、idle内部事件
          idle.stateFunc += () => {
              Debug.Log(idle.stateName);
          };
          //4、run内部事件
          run.stateFunc += () => {
              Debug.Log(run.stateName);
          };
          //5、切换事件Idle --> Run
          idle.RegisterTranslate (run, () => {
              if(stateController.GetFloatParams("Speed") > 0.5f)
              {
                  return true;
              }
              return false;
          });
          //5、切换事件Run --> Idle
          run.RegisterTranslate (idle, () => {
              if(stateController.GetFloatParams("Speed") <= 0.5f)
              {
                  return true;
              }
              return false;
          });
      }
    
      void Update()
      {
          if (test)
          {
              //6、切换参数,调整状态
              stateController.SetFloatParams("Speed",1);
          }
          else
          {
              stateController.SetFloatParams("Speed",0);
          }
      }
    }
    结束语
    这个工具类中用到了多线程的处理,其中各个状态的线程是持续执行的,所以后期还会继续改进,如果读者朋友有哪些更好的建议和意见,欢迎评论。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值