游戏框架之状态机(一)

来源:互联网 发布:淘宝网男装夏装新款 编辑:程序博客网 时间:2024/06/06 07:04

近期可能会更新多一点博客更新。

或许是这个样子,毕竟我是很懒的人,能在笔记本上做笔记的事情,我是从来不会再博客上留下痕迹的。

但涉及的框架知识,肯定要经常会回顾与更改,索性就拿上博客做为一个记录。

以后再要去更改的时候也方便一点。


作为进阶,当然是在参考了成熟的游戏框架之后所具有的新的想法。

所代表的实际意义不明,但起码能给与没有框架之说的项目一个更好的开发思路。

这里不提及MVC等理论性大于实践性的框架,毕竟研究透彻之后才能结合unity达到一个比较好的效果,不然在此之前无实际作用。

因为unity以Component组件方式就已经算是一种框架了。



讲讲正文:

首先先要明白为什么要用这个状态机。

我的解释是UI框架,角色控制,AI等等

具体可以了解下

http://www.manew.com/thread-41889-1-1.html

他这个例子是UI整个框架切换就是用的状态机。


来看下整个思路。

首先有个IState的接口类。

有一个状态管理类StateMachine来控制状态的注册,切换,以及增删查(很像数据库有没有)

每一个状态都是一个单独的类(UI可以不用,可以用一个类注册,然后用不同的回调函数做响应)继承IState接口。


所以我们只需要控制管理类StateMachine就能实现状态机的改变。

是不是很棒,上代码


using UnityEngine;using System.Collections;public interface IState {    /// <summary>    /// 获取这个状态机的状态    /// </summary>    /// <returns></returns>    ///     uint GetStateID();    /// <summary>    /// 进入这个状态    /// </summary>    /// <param name="machine">状态机</param>    /// <param name="PrevState">上一个状态</param>    /// <param name="param1">参数1</param>    /// <param name="param2">参数2</param>    void OnEnter(StateMachine machine ,IState PrevState ,object param1, object param2);    /// <summary>    /// 离开当前状态    /// </summary>    /// <param name="nextState">下一个进入状态</param>    /// <param name="param1">参数1</param>    /// <param name="param2">参数2</param>    void OnLeave(IState nextState, object param1, object param2);    void OnUpdate();    void OnFixedUpdate();    void OnLeteUpdate();}

using UnityEngine;using System.Collections;using System.Collections.Generic;public class StateMachine{    /// <summary>    /// 所有的状态集合    /// </summary>    private Dictionary<uint, IState> mStateDir = null;    /// <summary>    /// 当前状态    /// </summary>    private IState mCurrentState = null;    /// <summary>    /// 当前状态    /// </summary>    public IState CurrentState    {        get        {            return mCurrentState;        }    }        /// <summary>    /// 当前状态id    /// </summary>    public uint CurrentId    {        get        {            return mCurrentState ==null ?0:mCurrentState.GetStateID();        }    }    public StateMachine()    {        mStateDir = new Dictionary<uint, IState>();        mCurrentState = null;    }    /// <summary>    /// 注册一个状态    /// </summary>    /// <param name="state">状态对象</param>    /// <returns>成功还是失败</returns>    public bool RegisterState(IState state)    {        if(state ==null)        {            Debug.LogError("StateMachine.RegisterState state is null");            return false;        }        if(mStateDir.ContainsKey(state.GetStateID()))        {            Debug.LogError("state have this key,but stateID =" + state.GetStateID());            return false;        }        mStateDir.Add(state.GetStateID(),state);        return true;    }    /// <summary>    /// 移除一个状态    /// </summary>    /// <param name="stateId">状态Id</param>    /// <returns>当状态不存在或者状态正在运行,那么返回false</returns>    public bool RemoveState(uint stateId)    {        if(!mStateDir.ContainsKey(stateId))        {            return false;        }        if(mCurrentState != null && mCurrentState.GetStateID() ==stateId)        {            return false;        }        mStateDir.Remove(stateId);        return true;    }    /// <summary>    /// 获取一个状态    /// </summary>    /// <param name="stateId">状态id</param>    /// <returns></returns>    public IState GetStart(uint stateId)    {        IState state = null;        mStateDir.TryGetValue(stateId, out state);        return state;    }    /// <summary>    /// 停止当前状态    /// </summary>    /// <param name="param1">参数1</param>    /// <param name="param2">参数2</param>    public void StopState(object param1 ,object param2)    {        if(mCurrentState ==null)        {            return;        }        mCurrentState.OnLeave(null, param1, param2);        mCurrentState = null;    }    /// <summary>    /// 切换状态的回调    /// </summary>    public BetweenSwitchState BetweenSwitchStateCallBack = null;        /// <summary>    /// 切换状态回调委托    /// </summary>    /// <param name="from">当前状态</param>    /// <param name="to">要跳转的状态</param>    /// <param name="param1">参数1</param>    /// <param name="param2">参数2</param>    public delegate void BetweenSwitchState(IState from, IState to, object param1, object param2);    /// <summary>    /// 切换状态    /// </summary>    /// <param name="newStateId">要切换状态Id</param>    /// <param name="param1">参数1</param>    /// <param name="param2">参数2</param>    /// <returns>如果不存在这个状态或者当前状态等于要切换的状态Id,返回失败</returns>    public bool SwitchState(uint newStateId, object param1,object param2)    {        if(mCurrentState != null &&mCurrentState.GetStateID() ==newStateId)        {            return false;        }        IState newState = null;        mStateDir.TryGetValue(newStateId, out newState);        if(newState ==null)        {            return false;        }        if(mCurrentState !=null)        {            mCurrentState.OnLeave(newState, param1, param2);        }        IState oldState = mCurrentState;        mCurrentState = newState;        if(BetweenSwitchStateCallBack != null)        {            BetweenSwitchStateCallBack(oldState, mCurrentState, param1, param2);        }        newState.OnEnter(this, oldState, param1, param2);        return true;    }    /// <summary>    /// 判断当前状态是否是某个状态    /// </summary>    /// <param name="stateId"></param>    /// <returns></returns>    public bool IsInState(uint stateId)    {        return mCurrentState == null ? false : mCurrentState.GetStateID() == stateId;    }    public void OnUpdate()    {        if(mCurrentState != null)        {            mCurrentState.OnUpdate();        }    }    public void OnFixedUpdate()    {        if (mCurrentState != null)        {            mCurrentState.OnFixedUpdate();        }    }    public void OnLeteUpdate()    {        if (mCurrentState != null)        {            mCurrentState.OnLeteUpdate();        }    }}


这里我创建了一个cube切换状态来作为测试

using UnityEngine;using System.Collections;public class Test : MonoBehaviour {    [HideInInspector]    public StateMachine PlayStateMachine = new StateMachine();    /// <summary>    /// 角色状态ID    /// </summary>    public enum StateType:uint    {        LeftRight=0,        UpDown=1,    }    void Awake()    {        //注册状态        PlayStateMachine.RegisterState(new LeftRightState(this));        PlayStateMachine.RegisterState(new UpDownState(this));    }    void Update()    {        PlayStateMachine.OnUpdate();    }    void FixedUpdate()    {        PlayStateMachine.OnFixedUpdate();    }    void LeteUpdate()    {        PlayStateMachine.OnLeteUpdate();    }    void OnGUI()    {        if(GUI.Button(new Rect(0,0,100,100),"leftright"))        {            //切换状态            PlayStateMachine.SwitchState((uint)StateType.LeftRight, null, null);        }        else if (GUI.Button(new Rect(100, 100, 100, 100), "updown"))        {            //切换状态            PlayStateMachine.SwitchState((uint)StateType.UpDown, null, null);        }    }}


using UnityEngine;using System.Collections;public class LeftRightState : IState {    /// <summary>    /// 当前角色控制脚本引用    /// </summary>    Test mTest = null;    public LeftRightState(Test test)    {        mTest = test;    }    uint IState.GetStateID()    {        return (uint)Test.StateType.LeftRight;    }    void IState.OnEnter(StateMachine machine, IState PrevState, object param1, object param2)    {        Debug.Log("Test LeftRight OnEnter");    }    void IState.OnLeave(IState nextState, object param1, object param2)    {        Debug.Log("Test LeftRight OnLeave");    }    private bool isLeft = true;    void IState.OnUpdate()    {        if(isLeft)        {            mTest.transform.position += new UnityEngine.Vector3(-0.1f, 0, 0);            if(mTest.transform.position.x <= -1.5f)            {                isLeft = false;            }        }        else        {            mTest.transform.position += new UnityEngine.Vector3(0.1f, 0, 0);            if (mTest.transform.position.x >= 1.5f)            {                isLeft = true;            }        }            }    void IState.OnFixedUpdate()    {            }    void IState.OnLeteUpdate()    {            }}

using UnityEngine;using System.Collections;public class UpDownState : IState{        /// <summary>    /// 当前角色控制脚本引用    /// </summary>    Test mTest = null;    public UpDownState(Test test)    {        mTest = test;    }    uint IState.GetStateID()    {        return (uint)Test.StateType.UpDown;    }    void IState.OnEnter(StateMachine machine, IState PrevState, object param1, object param2)    {        Debug.Log("Test UpDown OnEnter");    }    void IState.OnLeave(IState nextState, object param1, object param2)    {        Debug.Log("Test UpDown OnLeave");    }    private bool isUp = true;    void IState.OnUpdate()    {        if(isUp)        {            mTest.transform.position += new UnityEngine.Vector3(0f, 0.1f, 0);            if (mTest.transform.position.y >= 1.5f)            {                isUp = false;            }        }        else        {            mTest.transform.position += new UnityEngine.Vector3(0f, -0.1f, 0);            if (mTest.transform.position.y <= -1.5f)            {                isUp = true;            }        }    }    void IState.OnFixedUpdate()    {            }    void IState.OnLeteUpdate()    {            }}

总体来说 功能很简单 但是,其核心思想还是很不错的。

可以拓展为UI的控制加载,NPC AI的控制,角色的状态机 等等。

只为抛砖引玉!



0 0
原创粉丝点击