有限狀態機主要是用于狀態之間的切換,狀態之間的切換也可以通過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();
}
總結一下:剛開始我們要把所有的狀態之間的切換加入到表里,后面我們就可以隨意的使用狀態了。以上主要是利用網絡通信舉的事例。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。