有限狀態機FSM詳解(一)
有限狀態機在維基百科中的解釋是:
有限狀態機(英語:finite-state machine,縮寫:FSM)又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。
至於為什麼要學FSM,FSM可以把模型的多狀態、多狀態間的轉換條件解耦。可以使維護變得容易,程式碼也更加具有可讀性,也更加藝術。
理解有限狀態機首先需要理解整個模型。我們把燈的開關作為示例,先看圖:
通過抽象化,我們提取出了其中幾個關鍵點:
1.狀態
2.動作
3.狀態過渡
4.轉換事件
5.FSM
首先分為狀態和動作,一般狀態都會對應一個動作,所以我們把狀態和動作放在狀態裡面,然後狀態過渡和過渡事件放在狀態過
渡裡面,最後再由狀態機驅動。於是一個狀態機模型就出來了,狀態、狀態過渡、狀態機。
他們三個之間的關係是:由狀態機管理和驅動狀態,然後由狀態和狀態內的狀態過渡
確定每個狀態之間的轉換。(重點、重點、重點)
其中我們最容易忽略的一點就是狀態過渡,這個是最不容易想到和抽象出來的一個物件。為什麼要把狀態過渡抽象出來呢?因為狀態過渡就是每個狀態之間互相轉換的條件,這個抽象出來後,以後就可以解耦每個狀態之間的轉換條件,少寫許多if - else ,並且會好維護許多。
我們現在開始設計整個狀態機。
(一)設計狀態機的介面
屬性:
名字(string Name{get;})
標記(string Tag{get;})
執行時間(float Timer{get;})
狀態轉換容器(List<ITransition> Transitions{get;})
狀態機父節點(IStateMachine Parent;)
方法:
進入狀態(void OnEnter(IState prev));
離開狀態(void OnExit(IState next));
持續執行狀態(每幀更新)(void OnUpdate(float delta))
新增狀態(void AddTransition(ITransition t));
設定父狀態機(void SetStateMachine(IStateMachine machine));
public interface IState
{
float Timer { get; }
string Name { get; }
string Tag { get; set; }
void OnEnter(IState prev);
void OnExit(IState next);
void OnUpdate(float deltaTime);
List<ITransition> Transitions { get; }
void AddTransition(ITransition transition);
IStateMachine Parent { get; }
void SetStateMachine(IStateMachine stateMachine);
}
(二)設計狀態轉換介面
屬性:
目標狀態(IState ToState{get;})
原狀態(IState FromState{get;})
名字(string Name{get;})
方法:
檢測條件(bool OnCheck();)
轉換回調(bool OnCompleteCallback();)
public interface ITransition
{
string Name { get; }
IState FromState { get; }
IState ToState { get; }
bool OnCheck();
bool OnCompleteCallBack();
}
(三)設計狀態機介面
屬性:
預設狀態(IState DefaultState{get;})
當前狀態(IState CurState{get;})
狀態容器(Dictionary<string, IState> States{get;})
方法:
新增狀態(void AddState(IState state));
移除狀態(void RemoveState(IState state));
獲取狀態(IState GetState(string name));
public interface IStateMachine
{
IState CurState { get; }
IState DefaultState { get; }
void AddState(IState state);
void RemoveState(IState state);
void SetCurState(IState state);
IState GetStateWithTag(string tag);
IState GetStateWithName(string name);
Dictionary<string, IState> States { get; }
}
先寫在這裡,後續再新增。gitee上已經把案例發上去了,著急使用和學習的朋友可以去上面提取。用的C#和Unity。基本原理明白了,哪裡都好用。歡迎大家提出意見和建議,虛心接受。