(2)行爲樹
行爲樹是一種無環圖。(樹都是無環的......)節點通過邊相連,出度節點爲父節點,入度節點爲子節點,無子節點(出度爲0)的節點爲葉子節點,無入度節點的節點爲根節點。標準行爲樹的父節點只能有1個(否則會出現環,但不是可逆環)
每個子樹定義了一個或簡單或複雜的行爲。根節點以指定頻率不斷的發出信號(Tick/Signal),信號傳播到每個節點,執行相應計算,並返回SUCCESS,FAILURE,RUNNING狀態。當狀態返回到根節點,一個Tick結束。
(3)節點類型
(4)節點優先級
比如,小機器人的自衛和躲避障礙的優先級,應該高於吃地上的小球的優先級。實際上,無論是Unity的Behavior Designer插件還是Unreal的內置行爲樹,都通過一種Abort Condition的機制,實現了這種優先級的處理。
當優先條件出現時,強制中斷當前RUNNING的節點。
(5)處理RUNNING STATE
[5.1]從頭開始執行,可以不會錯過優先級更高的系節點,但是效率低
[5.2]從RUNNING的節點開始執行,但是有可能會錯過優先級更改的節點。
(6)組合節點擴展:記住RUNNING節點。
如果節點A指令是去A點,節點B指令是去B點,Sequence是他們的父節點。A剛執行了一個Tick,馬上執行B的話,就會出現Agent在AB兩個方向顫抖。返回RUNNING狀態,下次還是用去A點這個指令開始執行,直到到達A點之後才執行去B點的指令,才能解決這個問題。
(7)組合節點擴展:概率隨機選擇子節點。
(8)保存數據
Unity Behavior Designer: Shared Variable+Global Variable.
UE4: Blackboard.
注意:每個樹運行實例會有自己的Blackboard作爲樹的數據存儲空間。如果將行爲樹類比爲一個Class,Blackboard則支撐了樹的對象實例(Object Instance)一千個Agent不會有一千顆行爲樹實例,但是卻會有一千個Blackboard。
圖1:行爲樹,與Blackboard與Agent的關係
實現要點
(1)需要一個可視化調試工具,能夠看到當前正在執行的節點(我的先省略了吧)。
樹必須知道上一幀打開的節點。這是爲了能夠在這一個Tick關掉我們沒有調用的節點。
(2)必須能夠序列化樹。
(3)必須有一些基礎事件:Open,Tick,Close
Open:Close狀態下,第一次調用Tick之前
Tick:每次接到脈衝
Close:Open狀態下,返回SUCCESS,FAILURE,或者被BTs強制關掉之後,調用之。
(4)樹只存儲結構,數據和Agent對象的引用,存放於Blackboard中。
UE4的源代碼還沒有來得及看。就Unity而言,BehaviorDesigner並沒有做到黑板。如果不使用External Tree的方式建立行爲樹,則每個GameObject都會建立一個行爲樹的實力,所以論效率來說,確實還是遠遠不如UE4的,尤其是在大規模和大數量行爲樹出現的時候。
即使使用了External Tree,也僅僅是通過“Pooled”也就是通過對象池去優化,並沒有真正做到樹的結構與樹的實例分離。所以就行爲樹而言,還是看看UE4的實現更加“科學”。
不過好在,Unity的插件BehaviorDesigner插件,至少做到了每個節點都是一個非Mono的類。使得不至於一棵樹就搞出來幾千個MonoBehavior來讓效率崩潰。
順便黑一下UE4 :-) 嘿嘿嘿嘿嘿嘿嘿嘿,純屬娛樂,別當真:-)
下次有時間會寫一個UE4 行爲樹 與BehaviorDesigner的對比。