最近打算好好研究一下行為樹,在使用行為樹之前,我們應該先理解行為樹的基本概念和相關的邏輯,然后我們就Unity3D平台下的行為樹插件的使用來進行學習行為樹。
什么是行為樹
如果了解過狀態機,會知道在行為樹之前,在實現AI用得比較多的技術是狀態機,狀態機理解起來是比較簡單的,即一個狀態過渡到另一個狀態,通過判斷將角色的狀態改變即可,如果學習過Unity的Mecanim動畫系統,會更加直觀的理解。
但是狀態機在狀態較多的情況下會使狀態之間的切換變得異常繁瑣,同時狀態之間很難復用。
在這種情況下,行為樹被發明出來,行為樹的優點如下:
- 行為樹提供大量的流程控制方法,使得狀態之間的改變更加直觀;
- 整個游戲AI使用樹型結構,方便查看與編輯;
- 方便調試和代碼編寫;
- 最重要的:行為樹方便制作編輯器,可以交由策划人員使用;
行為樹相關資料
這里給出我知道的行為樹相關的資料,大家有更好的資料希望可以告訴我:
其中,騰訊的開源項目提供了C#編寫的行為樹編輯器源碼和不錯的相關文檔(中文的哦),非常具有學習價值。
行為樹原理
行為樹是一種樹形結構,所以其可以分成3種節點類型:
(畫丑了點,見諒...)
- 紅色的節點:根節點,沒有父節點的節點;
- 藍色的節點:組合節點,有父節點和子節點的節點;
- 白色的節點:葉節點,沒有子節點的節點;
而編號為深度優先訪問的順序;
節點的返回
每個節點都會有一個返回值,可能出現的返回值有3個,如下:
- 運行中:表示當前節點還在運行中,下一次調用行為樹時任然運行當前節點;
- 失敗:表示當前節點運行失敗;
- 成功:表示當前節點運行成功;
下面我們來細說一下這幾個節點;
根節點
行為樹的入口節點,可以是任意類型的節點;
組合節點
行為樹的組合節點是由下面幾種類型來組成的:
選擇節點/優先選擇節點(Selector)
該節點會從左到右的依次執行其子節點,只要子節點返回“失敗”,就繼續執行后面的節點,直到有一個節點返回“運行中”或“成功”時,會停止后續節點的運行,並且向父節點返回“運行中”或“成功”,如果所有子節點都返回“失敗”則向父節點返回“失敗”。
隨機選擇節點(Random Selector)
之前的選擇節點是有優先級順序的,而隨機選擇節點的執行順序是隨機的。但每個節點只會執行一次,比如包含子節點:A、B、C、D、E;使用隨機選擇節點,執行順序可能是:D、E、A、C、B或其他組合。其它規則同選擇節點一致。
順序節點(Sequence)
該節點會從左到右的依次執行其子節點,只要子節點返回“成功”,就繼續執行后面的節點,直到有一個節點返回“運行中”或“失敗”時,會停止后續節點的運行,並且向父節點返回“運行中”或“失敗”,如果所有子節點都返回“成功”則向父節點返回“成功”。
修飾節點(Decorator)
修飾節點只包含一個子節點,用來以某種方式來改變這個子節點的行為。
修飾節點的類型比較多,這里我們說一些比較常見的修飾節點:
Until Success和Until Failure
循環執行子節點,直到返回“成功”或“失敗”為止。
比如Until Success在子節點返回“運行中”和“失敗”時都會向父節點返回“運行中”,返回“成功”時向父節點返回“成功”。
Until Failure在子節點返回“運行中”和“成功”時都會向父節點返回“運行中”,返回“失敗”時向父節點返回“成功”。
Limit
執行子節點一定次數后強制返回“失敗”。
當子節點運行指定次數后還沒有返回“失敗”則該節點向父節點返回失敗。
Timer
子節點不會立即執行,而會在指定的時間到達后才開始執行。
TimeLimit
指定子節點的最長運行時間,如果子節點在指定時間到達后還在運行則強制返回“失敗”。
Invert
對子節點的返回結果取“非”,即子節點返回“成功”則該節點返回“失敗”,子節點返回“失敗”則該節點返回成功。
並行節點(Parallel)
不同於選擇和順序節點依次執行每個節點,並行節點是“同時”執行所有的節點,然后根據所有節點的返回值判斷最終返回的結果。
這里的“同時”會迷惑住不少人,實際上,行為樹是運行在單一線程上的,並不會在並行節點上開多個線程來進行真正的同時執行,那么“同時”的含義是什么?
我們知道選擇或順序節點會依次執行所有的子節點,當子節點返回“成功”或“失敗”后就會停止后續節點的執行,而並行節點也會依次執行所有的子節點,無論子節點返回“成功”或“失敗”都會繼續運行后續節點,保證所有子節點都得到運行后在根據每個子節點的返回值來確定最終的返回結果。
並行節點一般可以設定退出該節點的條件,比如:
- 當全部節點都返回成功時退出;
- 當某一個節點返回成功時退出;
- 當全部節點都返回成功或失敗時退出;
- 當某一個節點返回成功或失敗時退出;
- 當全部節點都返回失敗時退出;
- 當某一個節點返回失敗時退出;
葉節點
條件節點(Condition)
條件節點可以理解為一個if判斷語句,當條件的測試結果為true時向父節點傳遞success,結果為false時向父節點傳遞failure;
該節點搭配一些組合節點可以完成各種判斷跳轉,比如搭配順序節點,可以做出“是否看見敵人”->“向敵人開火”的AI;
行為節點(Action)
行為節點用來完成具體的操作,比如,移動到目標點,執行開火等代碼邏輯,多種情況下行為節點會返回running和success;
行為節點也可能會使用多幀來完成;
子樹的復用
我們設計好的行為樹可以在其他樹中作為一顆子樹來進行使用,最大可能的復用子樹可以減少開發量。
行為樹和狀態機的選擇
行為樹並不能完全的替代狀態機,兩者都可以用來處理AI編寫問題,但行為樹是“輪詢”機制,而狀態機是“事件”機制,在最終使用之前一定要好好權衡和選擇才行。