面向對象狀態機框架

這裏寫圖片描述
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狀態每幀使用這個方法
    }
}
發佈了21 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章