溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Unity有限狀態機實現

發布時間:2020-07-18 21:26:07 來源:網絡 閱讀:2960 作者:jxw167 欄目:開發技術

 有限狀態機主要是用于狀態之間的切換,狀態之間的切換也可以通過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();
  }

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女