13、行為樹原理
AI最重要的環節就是行為樹。我們將解釋什么是行為樹、為何它如此重要,以及構建行為樹需要哪些元素。
借助行為樹,我們可以輕松控制並顯示AI的決策制定過程。行為樹是一種將AI在場景中的決策制定模型進行可視化的方法。通過觀察行為樹的可視化結構,我們可以清晰地了解行為樹的執行方式和執行順序,而不必了解每個節點的具體工作方式。行為樹的執行順序由行為樹中各個節點的位置決定。
任務和合成可用於控制AI如何做出反應以及如何執行行為。任務節點:任務是行為樹中的一種節點,它們下面無法再添加其他節點。它們是行為樹分支的終點(但不是行為樹的終點!)這使得它們還被稱為葉節點。任務狀態:任務擁有三種不同的狀態:成功、失敗或執行。無論任務成功還是失敗,行為樹都會接着執行下一個節點——在這一點上,行為樹同樣遵循從左到右的執行順序。無論任務成功還是失敗,行為樹都會接着執行下一個節點——在這一點上,行為樹同樣遵循從左到右的執行順序。
如果僅僅依靠任務節點,行為樹能夠實現的復雜程度還比較有限。這就需要用到合成節點了。合成是AI執行分支的根。它們不會像葉節點那樣執行操作,但能創建一個結構,並能根據其子節點的成功或失敗來控制順序。
選擇器合成節點會執行它下面的子節點。只要有子節點返回成功,那么它就是成功的。相反,如果所有子節點都返回失敗,那么它就是失敗的。你可以把它理解成它正在試圖選擇最合適的任務。由於行為樹采用從左到右的執行順序,我們可以把優先級最高的任務放在左邊。想想看,如果你想打開一扇門,你可以用鑰匙打開門,把鎖撬開,或者破門而入。采用哪種方法並不重要,能達到目的即可。如果我們希望AI用鑰匙開門而非破門而入,我們就應該把這個任務放在最左邊。
序列合成節點會按照序列順序遍歷子節點,當且僅當所有子節點都成功執行后,它才會返回成功。如果某個步驟未能成功執行,它就會返回失敗。這個節點的行為方式與人們處理障礙時的行為有點類似。
在很多情況下,我們需要按特定順序執行,如果我們卡住了,就無法跳過這步執行下一步。比如打開一扇門。你需要打開門,穿過門,然后關上門。你不可能先穿過門,然后打開門,再關上門。
14、構建第一個行為樹
為建立行為樹,我們首先需要創建必要的資源,然后為AI控制器添加功能,以便自行運行行為樹,最后創建第一個行為樹分支,把此前創建的隨機漫步邏輯替換成更靈活的模式。
我們先創建必要的資源,首先在“內容“>”ThirdPersonBP“>”藍圖”中新建一個目錄,把它命名為”BT_Assets“,打開目錄,然后右鍵點擊內容瀏覽器,選擇”AI“,然后選擇”行為樹“,將這個資源命名為”BT_EnenmyAI“,前綴”BT“表示這個資源是行為樹。再次右鍵點擊內容瀏覽器,選擇”AI“,然后選擇”黑板“,將這個資源命名為”BB_EnenmyAI “,下一步是確保我們的AI能夠使用這個行為樹。為此,我們需要打開AI控制器。在內容瀏覽器中,打開”藍圖“目錄,打開”AIC_ThirdPersonCharacter“。右擊點擊事件圖表,然后輸入”event on possess“,拖動這個事件的執行引腳,然后輸入”run behavior tree“,在”BTAsset“下拉菜單中選擇新建的行為樹資源,按F7編譯。保存藍圖。
接下來,我們要確保將我們創建的黑板與行為樹相關聯,回到內容瀏覽器中的“BT_Assets“目錄,打開”BT_EnenmyAI“,在細節面板中找到”AI“分段,確保選中黑板資源”BT_EnemyAI“。接下來我們需要在黑板的某個地方創建一個變量來保存目標位置,以便作為全新隨機漫游邏輯中的AI的移動目的地。為此,我們新建一個黑板鍵,直接選中右框的”黑板“選項卡,在新建選項上選擇向量類型的黑板鍵,將這個向量命名為”Target Location“。
下一步是新建一個任務,用於封裝我們之前編寫的所有隨機漫游邏輯。和之前的版本一樣,這個任務會以AI的當前位置為起點,找到一個可抵擋的有效位置。在“行為樹“窗口中選擇”新建任務”,然后選擇“BTTask BlueprintBase”,這樣就會新建一個任務並打開事件圖表。在進一步之前,先回到內容瀏覽器的“BT_Assets“目錄,將剛才創建的任務命名為“BTT_Find_Navigablelocation”,可以新建一個文件保存這個任務。
打開剛才新建的任務,新建一個事件叫做“Receive Execute AI”,當行為樹嘗試執行這個任務時,就會觸發這個事件,為此,右鍵點擊事件圖表,然后輸入“Event Receive Execute AI”.
在右鍵選擇“get random reachable point in radius”函數。拖動“Event_Receive_Excute_AI”的“Controlled Pawn”引腳,然后輸入“get actor location”,將“get actor location”的返回值連到“get random reachable point in radius”的“orgin”,將其半徑設置為1000。
現在我們需要處理這個函數返回的隨機位置參數。和之前的邏輯不同,一旦這個任務完成,它包含的所有信息都會被銷毀。我們要做的是,把這個隨機位置從任務傳遞給行為樹,再傳遞給黑板。拖動“get random reachable point in radius”的“Romdom location”,然后輸入“Set Blackboard Value as Vector”,注意,這個函數需要的第二條信息是一個向量值。拖動“key”鍵選擇“提升為變量”,將這個新變量命名為“Target location key”.最后將“Event Receive Execute AI”的執行腳連到“Set Blackboard Value as Vector”的執行引腳。右鍵點擊事件圖表,然后輸入“Finish Execute”,將“Set Blackboard Value as Vector”的執行引腳連到“Finish Execute” 的執行引腳,將“get random reachable point in radius”的”Return value”連到“Success”變量上,這意味着只要函數能夠找到隨機位置,這個任務就會被視作成功。