有限状态机主要是用于状态之间的切换,状态之间的切换也可以通过Switch Case或者if else实现。由于使用二者实现主要是对用用户扩展不是很方便,所以就有了有限状态机的概念。 有限状态机主要是用于不同的状态频繁的切换。那在Unity中我们如何定义有限状态机?其实有限状态机主要包括三部分,切换状态,进入状态,退出状态。接下来我们就利用Unity实现有限状态机并给大家展示如何应用。
首先我们定义FSMState.cs脚本,我们通过委托对函数状态进行切换.代码如下:
using System;
using System.Collections.Generic;
namespace FSM
{
public class FSMState
{
private int stateName;
private Dictionary<int, int> transitions = new Dictionary<int, int>();
//设置状态名字
public void SetStateName(int newStateName)
{
this.stateName = newStateName;
}
//获取状态名字
public int GetStateName()
{
return this.stateName;
}
//加入状态
public void AddTransition(int transition, int outputState)
{
this.transitions[transition] = outputState;
}
//使用状态
public int ApplyTransition(int transition)
{
int result = this.stateName;
if (this.transitions.ContainsKey(transition))
{
result = this.transitions[transition];
}
return result;
}
}
}
以上的类定义的是状态。下面我们定义对外接口,有限状态机FStateMachine.cs脚本
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace FSM
{
public class FStateMachine
{
//声明了一个委托用于状态之间的切换
public delegate void OnStateChangeDelegate(int fromStateName, int toStateName);
private List<FSMState> states = new List<FSMState>();
private volatile int currentStateName;
public FiniteStateMachine.OnStateChangeDelegate onStateChange;
private object locker = new object();
//增加状态
public void AddState(object st)
{
int stateName = (int)st;
FSMState fSMState = new FSMState();
fSMState.SetStateName(stateName);
this.states.Add(fSMState);
}
//增加所有状态
public void AddAllStates(Type statesEnumType)
{
IEnumerator enumerator = Enum.GetValues(statesEnumType).GetEnumerator();
try
{
while (enumerator.MoveNext())
{
object current = enumerator.Current;
this.AddState(current);
}
}
finally
{
IDisposable disposable;
if ((disposable = (enumerator as IDisposable)) != null)
{
disposable.Dispose();
}
}
}
//该函数是表示从from到to的转换
public void AddStateTransition(object from, object to, object tr)
{
int num = (int)from;
int outputState = (int)to;
int transition = (int)tr;
FSMState fSMState = this.FindStateObjByName(num);
fSMState.AddTransition(transition, outputState);
}
public int ApplyTransition(object tr)
{
object obj = this.locker;
Monitor.Enter(obj);
int result;
try
{
int transition = (int)tr;
int num = this.currentStateName;
this.currentStateName = this.FindStateObjByName(this.currentStateName).ApplyTransition(transition);
if (num != this.currentStateName)
{
if (this.onStateChange != null)
{
this.onStateChange(num, this.currentStateName);
}
}
result = this.currentStateName;
}
finally
{
Monitor.Exit(obj);
}
return result;
}
public int GetCurrentState()
{
object obj = this.locker;
Monitor.Enter(obj);
int result;
try
{
result = this.currentStateName;
}
finally
{
Monitor.Exit(obj);
}
return result;
}
public void SetCurrentState(object state)
{
int toStateName = (int)state;
if (this.onStateChange != null)
{
this.onStateChange(this.currentStateName, toStateName);
}
this.currentStateName = toStateName;
}
private FSMState FindStateObjByName(object st)
{
int num = (int)st;
FSMState result;
foreach (FSMState current in this.states)
{
if (num.Equals(current.GetStateName()))
{
result = current;
return result;
}
}
result = null;
return result;
}
}
}
以上定义的是有限状态机类,那接下来我给大家展示如何实现。
我们可以先初始化状态,那如何初始化,看下面的函数:
private void InitStates()
{
this.fsm = new FStateMachine();
this.fsm.AddAllStates(typeof(TCPSocketLayer.States));
this.fsm.AddStateTransition(TCPSocketLayer.States.Disconnected, TCPSocketLayer.States.Connecting, TCPSocketLayer.Transitions.StartConnect);
this.fsm.AddStateTransition(TCPSocketLayer.States.Connecting, TCPSocketLayer.States.Connected, TCPSocketLayer.Transitions.ConnectionSuccess);
this.fsm.AddStateTransition(TCPSocketLayer.States.Connecting, TCPSocketLayer.States.Disconnected, TCPSocketLayer.Transitions.ConnectionFailure);
this.fsm.AddStateTransition(TCPSocketLayer.States.Connected, TCPSocketLayer.States.Disconnected, TCPSocketLayer.Transitions.Disconnect);
this.fsm.SetCurrentState(TCPSocketLayer.States.Disconnected);
}
首先实例化一个有限状态机对象fsm,然后我们做了一个枚举值TCPSocketLayer,然后将其加入状态转换函数AddAllStates,比如AddStateTransition(TCPSocketLayer.States.Disconnected, TCPSocketLayer.States.Connecting, TCPSocketLayer.Transitions.StartConnect);
表示是从Disconnected到Connecting之间的转换。
函数的末尾是设置当前状态为Disconnected。
如果我们关闭连接,我们可以使用Disconnect状态,如下函数所示:
public void Kill()
{
this.fsm.ApplyTransition(TCPSocketLayer.Transitions.Disconnect);
this.connection.Close();
}
总结一下:刚开始我们要把所有的状态之间的切换加入到表里,后面我们就可以随意的使用状态了。以上主要是利用网络通信举的事例。