我們知道狀態機是ai(當然,不光是ai了)中常用的一種架構,有很多中實現方式,總體來說對於表達簡單邏輯,還是很有幫助的,而且實現簡單,甚至用乙個switch-case就可以了,但在實踐中狀態機有乙個致命的缺點,當狀態一旦多了之後,它的跳轉就會變的不可維護,假設有n個狀態的話,那我們就需要維護最多n*n的跳轉鏈結(因為狀態機允許自己跳**己),而且對於當前處在的狀態而言,我不能知道我的跳轉歷史,也就是說,我很難知道為什麼我會在這個狀態裡。這也就是為什麼行為樹現在成為相對主流的ai架構的原因。下圖就演示了多狀態間的跳轉鏈結,對於ai程式設計師來說是非常頭疼的。
所以一般而言,除非是只有兩三個狀態的簡單狀態機,如果想要用狀態機作為ai整體架構的話,現在都會選擇層次化狀態機結構(hfsm),並在一定程度上規範狀態機的跳轉行為。據我所知,微軟的著名遊戲光環2(halo2)裡就用到了層次化狀態機的結構。hfsm就是為了減少跳轉鏈結而做出的努力,舉個決策小狗行為的例子,我們對小狗定義了有很多行為,比如跑,吃飯,睡覺,咆哮,撒嬌,搖尾巴等等,如果每個行為都是乙個狀態,用常規狀態機的話,我們就需要在這些狀態間定義跳轉,比如在「跑」的狀態下,如果累了,那就跳轉到「睡覺」狀態,再如,在「撒嬌」的狀態下,如果感到有威脅,那就跳轉到「咆哮」的狀態等等,我們會考量每乙個狀態間的關係,定義所有的跳轉鏈結,建立這樣乙個狀態機。如果用層次化的狀態機的話,我們就先會把這些行為「分類」,把幾個小狀態歸併到乙個狀態裡,然後再定義高層狀態和高層狀態中內部小狀態的跳轉鏈結,可能這樣說有點暈,還是看圖吧
從上圖可以看到,其實層次化狀態機從某種程度上,就是限制了狀態機的跳轉,而且狀態內的狀態是不需要關心外部狀態的跳轉的,這樣也做到了無關狀態間的隔離,比如對於小狗來說,我們可以把小狗的狀態先定義為疲勞,開心,憤怒,然後這些狀態裡再定義小狀態,比如在開心的狀態中,有撒橋,搖尾巴等小狀態,這樣我們在外部只需要關心三個狀態的跳轉(疲勞,開心,憤怒),在每個狀態的內部只需要關心自己的小狀態的跳轉就可以了。這樣就大大的降低了狀態機的複雜度,另外,如果覺得兩層的狀態機還是狀態太多的話,可以定義更多的狀態層次以降低跳轉鏈結數。
說回到和同事討論的事情,當然同事的需求並不是用在ai中,是為了處理ui和網路非同步請求的問題,我們知道,在網路遊戲的ui中,經常需要給網路傳送非同步請求,然後得一些資料,正因為這些請求是非同步的,所以需要在傳送後等待網路返回結果,當這些請求很多的時候,很容易在ui端產生混亂(所以,一般來說,在專案中ui的bug是最多的:)),所以他提出了一種結構來改善這樣的問題,總結下來,其實就類似於這種ai中常用的這種層次化狀態機的概念,不過針對他的需求,還增加了乙個並行的概念,也就是在乙個狀態內部,可能有多個同時執行的狀態機(因為有同時多個的網路非同步請求),所以當收到乙個跳轉請求或者訊息的時候,還需要決定是哪個狀態機需要跳轉。另外為了防止跳轉混亂,我們還談到給狀態機加更多跳轉限制,增加語義支援等等問題。
最後,對於狀態機,列出一些小的tips作為總結,希望對大家有所幫助
Wifi層次結構狀態機
android2.3中wifi的狀態都是在wifistatetracker中維護的,4.0中將wifi的狀態全部放到wifistatemachine中維護的。今天不是深究wifi的問題,只以wifi為例,來分析層次結構狀態機的原理。wifistatemachine繼承於statemachine,st...
狀態機 狀態機0
近半年都忙於做專案,沒有太多的時間去整理和總結在專案中用過的技術 個人還是覺得技術需要總結提煉和沉澱的,忙到沒時間去總結提公升其實不 是什麼好事,這次講下狀態機,在戰鬥型別的遊戲中角色有多種不同的狀態,而狀態的切換錯綜複雜,23種設計模式中有一種模式叫做狀態模式,不過 這種模式是把狀態切換條件放到各...
python 狀態機 Python 狀態機
class statemachine def init self self.handlers 狀態轉移函式字典 self.startstate none 初始狀態 self.endstate 最終狀態集合 引數name為狀態名,handler為狀態轉移函式,end state表明是否為最終狀態 de...