FSM,有限狀態機,可以理解成是對行為邏輯的抽象,就好象人在生活中會做出各種行為,例如吃飯、睡覺等,這些所有我們都看作是“行為”的分支,由大腦決定每種行為具體是什么實施。在整個FSM架構中,其實與上面解釋一致,首先有一個狀態基類stateObject,里面有三個方法,分別是狀態前、狀態中、狀態后。所有具體行為都要繼承這個基類,在這三個方法中具體實現各種方法的邏輯。然后,需要一個stateManager(大腦)狀態管理類來管理這些狀態,特別注意的是里面changeState方法,他是狀態跳轉的關鍵。至於如果存儲各種狀態,你可以用list類 ,字典類等等。有限狀態機是把一個對象的行為分解稱為易於處理的“塊”或狀態。
例如將人的行為抽象成3個,分別是吃飯、睡覺、上班。上班族,只有吃飯、睡覺、上班三種行為,我們把這三種行為放進我們的大腦,即stateManager。那我們從什么行為開始呢?(其實這里就是initState),隨便挑一個,默認為睡覺。之前說過,每個行為都有三個狀態(前、中、后),當我們進入睡覺行為時,首先進入的是睡覺前狀態(該狀態只執行一次),然后進入睡覺中,真正的邏輯是在這里執行的,它會不停檢查什么時候睡醒了,符合條件后跳到其他狀態,當要進行跳轉時,還會執行一次睡覺后狀態,其實前、后狀態我理解成當要執行或結束某種行為時,你要額外做的事情。例如,睡覺前我要帶個眼罩。(放到游戲開發里可以進行一些賦值操作,或者調用其他類的方法,例如一些特效)。因為它編程快速簡單,易於調試,性能高,與人類思維相似從而便於梳理,靈活且容易修改
FSM的優點就是因為它編程快速簡單,易於調試,性能高,與人類思維相似從而便於梳理,靈活且容易修改。
以下是一個自己寫的實例代碼,可供大家參考
首先創建一個抽象狀態基類,里面有3個抽象方法,分別是進入狀態,離開狀態,更新狀態的方法
using System.Collections; using System.Collections.Generic; using UnityEngine; public abstract class StateObject { //狀態控制機 protected StateManger sm; //構造函數 public StateObject(StateManger _sm) { sm = _sm; } //進入狀態方法 public abstract void EnterState(); //離開狀態方法 public abstract void ExitState(); //更新狀態方法 public abstract void UpdateState(); }
然后根據具體的情況創建具體的狀態類(繼承與狀態基類),我這里實現了3個具體的狀態類,分別是人物默認狀態,移動狀態,死亡狀態
默認狀態方法
using System.Collections; using System.Collections.Generic; using UnityEngine; public class IdleState : StateObject { public IdleState(StateManger _sm):base(_sm) { } //進入狀態方法 public override void EnterState() { Debug.Log("進入待定狀態"); } //離開狀態方法 public override void ExitState() { Debug.Log("離開待定狀態"); } //更新狀態方法 public override void UpdateState() { Debug.Log("更新待定狀態"); if (Input.GetKeyDown(KeyCode.M)) { sm.ChangeState("Move"); } else if (Input.GetKeyDown(KeyCode.D)) { sm.ChangeState("Die"); } } }
移動狀態方法
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MoveState : StateObject { public MoveState(StateManger _sm) :base(_sm) { } public override void EnterState() { Debug.Log("進入移動狀態"); } public override void ExitState() { Debug.Log("離開移動狀態"); } public override void UpdateState() { Debug.Log("更新移動狀態"); if (Input.GetKeyDown(KeyCode.D)) { sm.ChangeState("Die"); } else if(Input.GetKeyDown(KeyCode.I)) { sm.ChangeState("Idle"); } } }
死亡狀態方法
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DieState : StateObject { public DieState(StateManger _sm):base(_sm) { } public override void EnterState() { Debug.Log("進入死亡狀態"); } public override void ExitState() { Debug.Log("離開死亡狀態"); } public override void UpdateState() { Debug.Log("更新死亡狀態"); if (Input.GetKeyDown(KeyCode.I)) { sm.ChangeState("Idle"); } } }
然后,需要一個stateManager(大腦)狀態管理類來管理這些狀態,特別注意的是里面changeState方法,他是狀態跳轉的關鍵,需要放在Update函數中,因為需要不斷檢測當前的狀態,檢測是否跳轉
using System.Collections; using System.Collections.Generic; using UnityEngine; public class StateManger { //利用字典存儲各種狀態 Dictionary<string, StateObject> Dic = new Dictionary<string, StateObject>(); //當前狀態 StateObject currentstate; //注冊狀態 public void Region(string statename,StateObject state) { if (!Dic.ContainsKey(statename)) { Dic.Add(statename,state); } } //設置默認狀態 public void SetDefat(string statename) { if (Dic.ContainsKey(statename)) { currentstate = Dic[statename]; currentstate.EnterState(); } } //改變狀態 public void ChangeState(string statename) { if (Dic.ContainsKey(statename)) { if (currentstate!=null) { currentstate.ExitState(); currentstate = Dic[statename]; currentstate.EnterState(); } } } //更新狀態 public void UpdateState() { if (currentstate!=null) { currentstate.UpdateState(); } } }
這樣一個簡單的有限狀態機就寫好了,然后我們可以在Unity里面利用一個實例來測試一下,我寫了一個控制物體狀態的腳本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestFsm : MonoBehaviour { //添加一個狀態機 StateManger stm = new StateManger(); void Start() {//注冊狀態 stm.Region("Idle", new IdleState(stm)); stm.Region("Die", new DieState(stm)); stm.Region("Move", new MoveState(stm)); //設置默認狀態 stm.SetDefat("Idle"); } // Update is called once per frame void Update() { //更新狀態的方法 stm.UpdateState(); } }
以上就是本人學習FSM的一點總結,如果有什么不對的地方,敬請大家指出,大家一起學習進步。