https://github.com/pzUH/HierarchicalStateMachine git
http://unitygems.com/fsm2/ github
一: 函數
有限狀態機用於管理遊戲中對象的行爲很是方便。 spa
最簡單的有限狀態機實現方式 對象
switch () 遞歸
case A: 遊戲
xxx 事件
一般switch塊放到 對象的update方法中,每幀更新狀態。 get
這種結構最大的問題是狀態沒有獲得封裝,而有限狀態機中狀態和狀態之間是存在轉化的,而轉化的過程當中,須要清理上個狀態的數據,準備下個狀態的數據,這樣就會形成大量的冗餘代碼,以及對當前狀態的混亂。 it
二:
具體的改善的作法:
抽象出分離狀態機 , 狀態, 以及轉化三個概念。
狀態機 包含一個當前狀態, 全部狀態, 包含update函數, 設置狀態函數。
每一個狀態都有一個名字,以及enter exit update 函數, 以及初始化轉化關係的函數。
一個轉化是屬於某個狀態的,在特定條件下,將當前狀態轉化到下一個狀態。
例如一個簡單的狀態機:
空閒狀態 <----->選擇狀態-------->移動狀態------>空閒狀態
初始化狀態機的過程就是:
增長空閒狀態
增長選擇狀態
增長移動狀態
初始化全部狀態的轉化關係
設定當前狀態是空閒狀態
三:
這時候如何觸發狀態轉化呢?
在每一個狀態的update的過程當中,都會檢測有沒有轉化條件知足,若是有則退出當前狀態,進入下一個狀態。
這個轉化是由狀態內部本身檢測來產生的,所以須要外部一直保持刺激信號,直到內部修改狀態爲止,這種行爲是電平觸發。
還有一種觸發方式是邊沿觸發,即外部每變化一次,就觸發一次狀態變化。
電平觸發存在的問題就是可能會丟失事件。
四:
可能存在這樣一種狀況:
一個事件發生致使A對象的狀態變化,B對象的狀態變化,這兩個變化可能會都修改相同的對象的屬性,這時候,應該確保邏輯上的前後順序,或者保證只修改屬於本對象的那些對象的屬性。
五:層次狀態機
對於一個複雜的對象可能有大量的狀態,一種簡化狀態數量的方法就是創建裝他的層次:
例如法師的攻擊狀態:
法師是連鎖閃電攻擊,攻擊完初始目標以後,會尋找下一個目標, 找到則攻擊,否者退出攻擊狀態;
而這三個子狀態都是屬於攻擊狀態這個大狀態的。
所以每一個狀態須要增長:
當前狀態所在層次
孩子屬性全部的子狀態
初始狀態
這樣狀態的進入,退出 和 轉化時,就要相應的考慮子狀態的問題:
進入一個狀態 若是有初始狀態則進入初始狀態, 遞歸初始化狀態。
退出一個狀態,一般是轉化到另一個狀態,則須要退出到下一個狀態的相應的層級。
六: 狀態機可配置action
一個狀態下的行爲可能由於當前上下文不一樣,而有不一樣。
例如一個對象受到攻擊以後, 根據攻擊對象不一樣,可能產生不一樣的效果,例如若是攻擊方是騎士,那麼可能會被擊退一格,攻擊方是忍者,可能就會交換彼此的位置。
一樣一我的攻擊另一個對象,根據被攻擊者不一樣也會產生不一樣的效果,例如若是是我方,那麼交換位置,若是是敵方則產生傷害。
所以給狀態添加action 屬性:
action 包含 enter exit update 函數
經過設定目標對象某個狀態下的action, 來達到同一狀態,不一樣表現行爲的目的!
這種設定須要在狀態轉化以前完成。