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狀態每幀使用這個方法
}
}