千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > unity状态机

unity状态机

来源:千锋教育
发布人:wjy
时间: 2022-07-29 17:01:00 1659085260

前言

众所周知,Unity在开发游戏的时候经常用到状态机,而通常情况下,我们会使用简单的枚举类型设置状态,然后通过调整枚举,来切换状态,在简单情况下是可以的,就像是Unity中Animator切换动画状态就是,直接通过动画片段的名称切换。而当状态很多的时候,直接切换就显得有些很不安全,而且友好性也不是很好,所以根据Unity中Animator这种通过条件切换状态的架构,我写了一个简单的状态机,给大家分享。

unity状态机

外部委托定义

    /// <summary>

    /// 状态内部事件委托

    /// </summary>

    public delegate void StateFunctionEventHandler();

    /// <summary>

    /// 状态条件判断委托

    /// </summary>

    public delegate bool StateTranslateEventHandler();

状态类

    /// <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());

            }

        }

    }

状态管理类

    /// <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);

                }

            }

        }

    }

实例应用

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);

        }

    }

}

结束语

这个工具类中用到了多线程的处理,其中各个状态的线程是持续执行的,所以后期还会继续改进,如果读者朋友有哪些更好的建议和意见,欢迎评论。

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT