全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

unity状态机

发布时间:2022-07-29 17:01:00
发布人:wjy

前言

众所周知,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);

        }

    }

}

结束语

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

相关文章

OKR与自驱力的关系是什么?

OKR与自驱力的关系是什么?

2023-10-14
office是什么软件类型?

office是什么软件类型?

2023-10-14
Cloud-IDE 是什么?

Cloud-IDE 是什么?

2023-10-14
主机和端系统之间有什么不同?

主机和端系统之间有什么不同?

2023-10-14

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取