溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Unity有限狀態(tài)機(jī)實(shí)現(xiàn)

發(fā)布時(shí)間:2020-07-18 21:26:07 來源:網(wǎng)絡(luò) 閱讀:2946 作者:jxw167 欄目:開發(fā)技術(shù)

 有限狀態(tài)機(jī)主要是用于狀態(tài)之間的切換,狀態(tài)之間的切換也可以通過Switch Case或者if else實(shí)現(xiàn)。由于使用二者實(shí)現(xiàn)主要是對(duì)用用戶擴(kuò)展不是很方便,所以就有了有限狀態(tài)機(jī)的概念。 有限狀態(tài)機(jī)主要是用于不同的狀態(tài)頻繁的切換。那在Unity中我們?nèi)绾味x有限狀態(tài)機(jī)?其實(shí)有限狀態(tài)機(jī)主要包括三部分,切換狀態(tài),進(jìn)入狀態(tài),退出狀態(tài)。接下來我們就利用Unity實(shí)現(xiàn)有限狀態(tài)機(jī)并給大家展示如何應(yīng)用。

首先我們定義FSMState.cs腳本,我們通過委托對(duì)函數(shù)狀態(tài)進(jìn)行切換.代碼如下:

using System;
using System.Collections.Generic;


namespace FSM
{
 public class FSMState
 {
  private int stateName;
  private Dictionary<int, int> transitions = new Dictionary<int, int>();

  //設(shè)置狀態(tài)名字
  public void SetStateName(int newStateName)
  {
   this.stateName = newStateName;
  }

  //獲取狀態(tài)名字
  public int GetStateName()
  {
   return this.stateName;
  }

  //加入狀態(tài)
  public void AddTransition(int transition, int outputState)
  {
   this.transitions[transition] = outputState;
  }

  //使用狀態(tài)
  public int ApplyTransition(int transition)
  {
   int result = this.stateName;
   if (this.transitions.ContainsKey(transition))
   {
    result = this.transitions[transition];
   }
   return result;
  }
 }
}

 

以上的類定義的是狀態(tài)。下面我們定義對(duì)外接口,有限狀態(tài)機(jī)FStateMachine.cs腳本

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace FSM
{
 public class FStateMachine
 {

//聲明了一個(gè)委托用于狀態(tài)之間的切換
  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();

    //增加狀態(tài)
  public void AddState(object st)
  {
   int stateName = (int)st;
   FSMState fSMState = new FSMState();
   fSMState.SetStateName(stateName);
   this.states.Add(fSMState);
  }

  //增加所有狀態(tài)
  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();
    }
   }
  }

 //該函數(shù)是表示從from到to的轉(zhuǎn)換
  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;
  }

 }
}
以上定義的是有限狀態(tài)機(jī)類,那接下來我給大家展示如何實(shí)現(xiàn)。

我們可以先初始化狀態(tài),那如何初始化,看下面的函數(shù):

  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);
  }

 

首先實(shí)例化一個(gè)有限狀態(tài)機(jī)對(duì)象fsm,然后我們做了一個(gè)枚舉值TCPSocketLayer,然后將其加入狀態(tài)轉(zhuǎn)換函數(shù)AddAllStates,比如AddStateTransition(TCPSocketLayer.States.Disconnected, TCPSocketLayer.States.Connecting, TCPSocketLayer.Transitions.StartConnect);
表示是從Disconnected到Connecting之間的轉(zhuǎn)換。

函數(shù)的末尾是設(shè)置當(dāng)前狀態(tài)為Disconnected。

如果我們關(guān)閉連接,我們可以使用Disconnect狀態(tài),如下函數(shù)所示:

  public void Kill()
  {
   this.fsm.ApplyTransition(TCPSocketLayer.Transitions.Disconnect);
   this.connection.Close();
  }

總結(jié)一下:剛開始我們要把所有的狀態(tài)之間的切換加入到表里,后面我們就可以隨意的使用狀態(tài)了。以上主要是利用網(wǎng)絡(luò)通信舉的事例。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI