面向对象状态机框架

来源:互联网 发布:淘宝自然流量没有了 编辑:程序博客网 时间:2024/06/06 01:08

这里写图片描述
1.状态类(Istate)当前状态下所有要执行的动作

using System.Collections;using System.Collections.Generic;using UnityEngine;namespace FSM{    /// <summary>    /// 状态接口    /// </summary>    public interface Istate    {        /// <summary>        /// 状态名        /// </summary>        string Name { get; }        /// <summary>        /// 状态标签        /// </summary>        string Tag { set; get; }        /// <summary>        /// 当前状态的状态机        /// </summary>        IstateMachine Parent { get; set; }        /// <summary>        /// 从进入状态开始计算的时长        /// </summary>        float Timer { get; }        /// <summary>        /// 状态过度当前状态的所有过度        /// </summary>        List<ITransition> Transition { get; }        /// <summary>        /// 进入状态时的回调        /// </summary>        /// <param name="prev">上一个状态</param>        void EnterCallback(Istate prev);        /// <summary>        /// 退出状态时的回调        /// </summary>        /// <param name="next">下一个状态</param>        void ExitCallback(Istate next);        /// <summary>        /// Update的回调        /// </summary>        /// <param name="deltaTime">Time.deltaTime</param>        void UpdateCallback(float deltaTime);        /// <summary>        /// LateUpdate的回调        /// </summary>        /// <param name="deltaTime">Time.deltaTime</param>        void LateUpdateCallback(float deltaTime);        /// <summary>        /// FixUppdate的回调        /// </summary>        void FixUppdateCallback();        /// <summary>        /// 添加过度        /// </summary>        /// <param name="t">状态过度</param>        void AddTransition(ITransition t);    }}

1.1状态类实现

using System;using System.Collections;using System.Collections.Generic;using UnityEngine;namespace FSM{    public delegate void LexDelegate();    public delegate void LexDelegateState(Istate State);    public delegate void LexDelegateFloat(float f);    public class LexState : Istate    {        /// <summary>        /// 当进入状态时调用的事件        /// </summary>        public event LexDelegateState OnEnter;        /// <summary>        /// 当离开状态时调用的事件        /// </summary>        public event LexDelegateState OnExit;        /// <summary>        /// 当Update时调用的事件        /// </summary>        public event LexDelegateFloat OnUpdate;        /// <summary>        /// 当LateUpdate时调用的事件        /// </summary>        public event LexDelegateFloat OnLateUpdate;        /// <summary>        /// 当FixUpdate时调用的事件        /// </summary>        public event LexDelegate OnFixUpdate;        private string _name;//状态名        private string _tag;//状态标签        private IstateMachine _parent;//当前状态的状态机        private float _Timer;//计时器        private List<ITransition> _transition;//状态过度        /// <summary>        /// 构造方法        /// </summary>        /// <param name="name">状态名</param>        public LexState(string name)        {            _name = name;            _transition = new List<ITransition>();        }        /// <summary>        /// 状态名        /// </summary>        public string Name        {            get            {                return _name;            }        }        /// <summary>        /// 状态标签        /// </summary>        public string Tag        {            get            {                return _tag;            }            set            {                _tag = value;            }        }        /// <summary>        /// 当前状态的状态机        /// </summary>        public IstateMachine Parent        {            get            {                return _parent;            }            set            {                _parent = value;            }        }        /// <summary>        /// 从进入状态开始计算的时长        /// </summary>        public float Timer        {            get            {                return _Timer;            }        }        /// <summary>        /// 状态过度当前状态的所有过度        /// </summary>        public List<ITransition> Transition        {            get            {                return _transition;            }        }        /// <summary>        /// 添加过度        /// </summary>        /// <param name="t">状态过度</param>        public void AddTransition(ITransition t)        {            if(t!=null&&!_transition.Contains(t))            {                _transition.Add(t);            }        }        /// <summary>        /// 进入状态时的回调        /// </summary>        /// <param name="prev">上一个状态</param>        public virtual void EnterCallback(Istate prev)        {            //重置计时器            _Timer = 0;            //进入状态时系统调用OnEnter事件            if (OnEnter != null)            {                OnEnter(prev);            }        }        /// <summary>        /// 退出状态时的回调        /// </summary>        /// <param name="next">下一个状态</param>        public virtual void ExitCallback(Istate next)        {            //离开状态时系统调用OnEnter事件            if (OnExit != null)            {                OnExit(next);            }            //重置计时器            _Timer = 0;        }        /// <summary>        /// Update的回调        /// </summary>        /// <param name="deltaTime">Time.deltaTime</param>        public virtual void UpdateCallback(float deltaTime)        {            //累加计时器            _Timer += deltaTime;            //Update时系统会调用OnUpdate事件            if (OnUpdate!=null)            {                OnUpdate(deltaTime);            }        }        /// <summary>        /// LateUpdate的回调        /// </summary>        /// <param name="deltaTime">Time.deltaTime</param>         public virtual void LateUpdateCallback(float deltaTime)        {            //LateUpdate时系统会调用OnLateUpdate事件            if (OnLateUpdate!=null)            {                OnLateUpdate(deltaTime);            }        }        /// <summary>        /// FixUppdate的回调        /// </summary>        public virtual void FixUppdateCallback()        {            //FixUpdate时系统会调用OnFixUpdate事件            if (OnFixUpdate!=null)            {                OnFixUpdate();            }        }    }}

2.状态机类(IstateMachine)当前状态机类中的所有状态

using System.Collections;using System.Collections.Generic;using UnityEngine;namespace FSM{    /// <summary>/// 状态机接口/// </summary>    public interface IstateMachine    {        /// <summary>        /// 当前状态        /// </summary>        Istate CurrentState { get; }        /// <summary>        /// 默认状态        /// </summary>        Istate DefaultState { set; get; }        /// <summary>        /// 添加状态        /// </summary>        /// <param name="state">要添加的状态</param>        void AddState(Istate state);        /// <summary>        /// 删除状态        /// </summary>        /// <param name="state">要删除的状态</param>        void RemoveState(Istate state);        /// <summary>        /// 通过指定的tag值查找状态        /// </summary>        /// <param name="tag">状态 Tag值</param>        /// <returns>查找到的状态</returns>        Istate GetStateWithTage(string tag);    }}

2.1状态机类实现

using System;using System.Collections;using System.Collections.Generic;using UnityEngine;namespace FSM{    /// <summary>    /// 状态机类需要继承与状态类并实现状态机接口    /// </summary>    public class LexStateMachine : LexState, IstateMachine    {        private Istate _CurrentState;//当前状态        private Istate _DefaultState;//默认状态        private List<Istate> _States;//所有状态        private bool _isTransition = false;//是否正在过度        private ITransition _t;//当前正在执行的过度        /// <summary>        /// 构造方法        /// </summary>        /// <param name="name"></param>        public LexStateMachine(string  name,Istate defaultState):base(name)        {            _States = new List<Istate>();            _DefaultState = defaultState;        }        /// <summary>        /// 当前状态        /// </summary>        public Istate CurrentState        {            get            {                return _CurrentState;            }        }        /// <summary>        /// 默认状态        /// </summary>        public Istate DefaultState        {            get            {                return _DefaultState;            }            set            {                AddState(value);                _DefaultState = value;            }        }        /// <summary>        /// 添加状态        /// </summary>        /// <param name="state">要添加的状态</param>        public void AddState(Istate state)        {            if(state!=null &&!_States.Contains(state))            {                _States.Add(state);                //将加入的新状态的的Parent设置为当前状态机                state.Parent = this;                if(_DefaultState==null)                {                    _DefaultState = state;                }            }        }        /// <summary>        /// 删除状态        /// </summary>        /// <param name="state">要删除的状态</param>        public void RemoveState(Istate state)        {            //再状态机运行过程中不能够删除当前状态            if (_CurrentState == state)            {                return;            }            if (state != null && _States.Contains(state))            {                _States.Remove(state);                //将已经移除的Parent设置为空                state.Parent = null;                if (_DefaultState == state)                {                    _DefaultState = (_States.Count >= 1) ? _States[0] : null;                }            }        }        /// <summary>        /// 通过指定的tag值查找状态        /// </summary>        /// <param name="tag">状态 Tag值</param>        /// <returns>查找到的状态</returns>        public Istate GetStateWithTage(string tag)        {            return null;        }        public override void UpdateCallback(float deltaTime)        {            //检测当前是否再过度状态            if(_isTransition)            {                //检测当前执行的过度是否完成                if(_t.TransitionCallback())                {                    DoTransition(_t);                    _isTransition = false;                }                return;            }            base.UpdateCallback(deltaTime);            if(_CurrentState==null)            {                _CurrentState = _DefaultState;            }            List<ITransition> ts = _CurrentState.Transition;            int Count = _CurrentState.Transition.Count;            for (int i = 0; i < Count; i++)            {                ITransition t = ts[i];                if(t.ShouldBengin())                {                    _isTransition = true;                    _t = t;                    return;                }            }            _CurrentState.UpdateCallback(deltaTime);        }        public override void LateUpdateCallback(float deltaTime)        {            base.LateUpdateCallback(deltaTime);            _CurrentState.LateUpdateCallback(deltaTime);        }        public override void FixUppdateCallback()        {            base.FixUppdateCallback();            _CurrentState.FixUppdateCallback();        }        //开始执行过度        private void DoTransition(ITransition t)        {            _CurrentState.ExitCallback(t.To);            _CurrentState = t.To;            _CurrentState.EnterCallback(t.From);        }    }}

3.状态的转换过度类接口(ITransition)

using System.Collections;using System.Collections.Generic;using UnityEngine;namespace FSM{    /// <summary>/// 状态过度的接口/// </summary>    public interface ITransition    {        /// <summary>        /// 过度名        /// </summary>        string name { get; }        /// <summary>        /// 从哪个状态开始过度        /// </summary>        Istate From { get; set; }        /// <summary>        /// 要过度到哪个状态去        /// </summary>        Istate To { get; set; }        /// <summary>        /// 过度时的回调        /// </summary>        /// <returns>返回true过度结束返回false继续进行过度</returns>        bool TransitionCallback();        /// <summary>        /// 能否开始过度        /// </summary>        /// <returns>如果是True就开始进行过度如果是False就不进行过度</returns>        bool ShouldBengin();    }}

3.1状态过渡

using System;using System.Collections;using System.Collections.Generic;using UnityEngine;namespace FSM{    public delegate bool LexTransitionDelegate();    public class LexTransition : ITransition    {        private Istate _From;//原状态        private Istate _To;//目标状态        private string _name;//过度名        public event LexTransitionDelegate OnTransition;        public event LexTransitionDelegate OnCheck;//检测条件是否满足        /// <summary>        /// 构造方法        /// </summary>        /// <param name="Name"></param>        /// <param name="fromstate"></param>        /// <param name="tostate"></param>        public LexTransition(string Name, Istate fromstate, Istate tostate)        {            _name = Name;            _From = fromstate;            _To = tostate;        }        /// <summary>        /// 过度名        /// </summary>        public string name        {            get            {                return _name;            }        }        /// <summary>        /// 从哪个状态开始过度        /// </summary>        public Istate From        {            get            {                return _From;            }            set            {                _From = value;            }        }        /// <summary>        /// 要过度到哪个状态去        /// </summary>        public Istate To        {            get            {                return _To;            }            set            {                _To = value;            }        }        /// <summary>        /// 过度时的回调        /// </summary>        /// <returns>返回true过度结束返回false继续进行过度</returns>        public bool TransitionCallback()        {            if (OnTransition != null)            {                return OnTransition();            }            return true;        }        /// <summary>        /// 能否开始过度        /// </summary>        /// <returns>如果是True就开始进行过度如果是False就不进行过度</returns>        public bool ShouldBengin()        {            if (OnCheck != null)            {                return OnCheck();            }            return false;        }    }}

4.调用

using System.Collections;using System.Collections.Generic;using UnityEngine;using FSM;public class Test : MonoBehaviour {    public float speed; //Cube每秒钟移动的距离    private LexStateMachine _fsm;//状态机    private LexState Idle;//闲置状态    private LexState move;//移动状态    private LexTransition _IdleToMove;//Idle到Move的状态过度    private LexTransition _MoveToIdle;//Move到Idle的状态过度    private bool IsMove=false;//能否开始移动    // Use this for initialization    void Start () {        //初始化状态        Idle = new LexState("Idle");//创建状态        Idle.OnEnter += (Istate state) =>          {              Debug.Log("进入Idle状态");        };        move = new LexState("Move");        //移动状态的时候的逻辑        move.OnUpdate += (float f) =>          {              transform.position += transform.forward * f * speed;          };        _IdleToMove = new LexTransition("idlemove", Idle, move);//创建过渡状态        _IdleToMove.OnCheck += () =>          {              return IsMove;          };        Idle.AddTransition(_IdleToMove);//加入过渡状态链表        //_IdleToMove.OnTransition += () =>        //  {        //  };        _MoveToIdle = new LexTransition("moveIdle", move, Idle);        _MoveToIdle.OnCheck += () =>        {            return !IsMove;        };        move.AddTransition(_MoveToIdle);        _fsm = new LexStateMachine("Root", Idle);//创建状态机并加入状态        _fsm.AddState(move);    }    // Update is called once per frame    void Update () {        _fsm.UpdateCallback(Time.deltaTime);    }    void OnGUI()    {        if(GUILayout.Button("move"))        {            IsMove = true;        }        if(GUILayout.Button("Stop"))        {            IsMove = false;        }    }}
using System.Collections;using System.Collections.Generic;using UnityEngine;using FSM;public class LightControl : MonoBehaviour {    public float maxIntensity;    public float FadeSpeed;    private LexStateMachine _fsm;    private LexStateMachine _open;//open状态下的子状态声明    private LexState _close;    private LexTransition opentoclose;    private LexTransition closetoopen;    private LexState _changeIntensity;    private LexState _changeColor;    private LexTransition colortointensity;    private LexTransition intensitytocolor;    private bool isOpen=true;    private bool isAnimation;    private bool isResst;    private float target;    private Color targetColor;    private Color StartColor;    private float ColorTimer;    public bool ischangecolor;    private Light _light;    // Use this for initialization    void Start () {        InitFSM();        _light = GetComponent<Light>();    }    // Update is called once per frame    void Update () {        _fsm.UpdateCallback(Time.deltaTime);    }    //初始化状态机    private void InitFSM()    {        _changeIntensity = new LexState("changeIntensity");        _changeIntensity.OnEnter += (Istate State) =>          {              isAnimation = true;              isResst = true;          };        _changeIntensity.OnUpdate += (float f) =>        {            if (isAnimation)            {                if (isResst)                {                    if (Fadeto(maxIntensity))                    {                        isResst = false;                        isAnimation = false;                    }                }                else                {                    if (Fadeto(target))                    {                        isResst = true;                    }                }            }            else            {                target = Random.Range(0.3f, 0.7f);                isAnimation = true;            }        };        _changeColor = new LexState("changeColor");        _changeColor.OnEnter += (Istate State) =>          {              isAnimation = false;          };        _changeColor.OnUpdate += (float f) =>          {              if(isAnimation)              {                  if(ColorTimer>=1f)                  {                      isAnimation = false;                  }                  else                  {                      ColorTimer += Time.deltaTime ;                      _light.color = Color.Lerp(StartColor, targetColor, ColorTimer);                  }              }              else              {                  float r = Random.Range(0,0.5f);                  float g = Random.Range(0, 0.5f);                  float b = Random.Range(0, 0.5f);                  targetColor = new Color(r, g, b);                  StartColor = _light.color;                  ColorTimer = 0f;                  isAnimation = true;              }          };        colortointensity = new LexTransition("colortointensity",_changeColor,_changeIntensity);        colortointensity.OnCheck += () =>        {            return !ischangecolor;        };        _changeColor.AddTransition(colortointensity);        intensitytocolor = new LexTransition("intensitytocolor", _changeIntensity, _changeColor);        intensitytocolor.OnCheck += () =>        {            return ischangecolor;        };        _changeIntensity.AddTransition(intensitytocolor);        _open = new LexStateMachine("open", _changeIntensity);//子状态的加入        _open.AddState(_changeColor);             _close = new LexState("close");        _close.OnEnter += (Istate State) =>        {            _light.intensity = 0;        };        opentoclose = new LexTransition("OpenClose", _open, _close);        opentoclose.OnCheck += () =>        {            return !isOpen;        };        //opentoclose.OnTransition += () =>        //{        //    return Fadeto(0);        //};        _open.AddTransition(opentoclose);        closetoopen = new LexTransition("CloseOpen", _close, _open);        closetoopen.OnCheck += () =>        {            return isOpen;        };        closetoopen.OnTransition += () =>        {            return Fadeto(maxIntensity);        };        _close.AddTransition(closetoopen);        _fsm = new LexStateMachine("Cube", _open);        _fsm.AddState(_close);    }    void OnGUI()    {        if (GUI.Button(new Rect(150f,30f,55f,28f),"open"))        {            isOpen = true;        }        if (GUI.Button(new Rect(150f, 65f, 55f, 28f), "Close"))        {            isOpen = false;        }    }    //将灯光光强渐变到指定的值    private bool Fadeto(float f)    {        if(Mathf.Abs(_light.intensity-f)<=0.05f)        {            _light.intensity = f;            return true;        }        else        {            int flag = _light.intensity > f ? -1 : 1;            _light.intensity += Time.deltaTime * FadeSpeed*flag;            return false;        }    }}
using System.Collections;using System.Collections.Generic;using UnityEngine;using FSM;public class CubeMoveState : LexState{    public CubeMoveState() : base("CubeMoveState")    {    }    public override void EnterCallback(Istate prev)    {        //进入移动状态打印上一个状态的名字        Debug.Log(prev.Name);    }    public override void UpdateCallback(float deltaTime)    {       //每当处于move状态每帧使用这个方法    }}
原创粉丝点击