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状态每帧使用这个方法
}
}