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”變數上,這意味著只要函式能夠找到隨機位置,這個任務就會被視作成功。