UE4藍圖AI角色製作(七)之追逐玩家
- 2021 年 10 月 21 日
- 筆記
15、追逐玩家
現在我們的AI無法做出任何決策,它總是執行相同的決策。我們先把感知系統中的相關信息提供給AI,讓AI知道如何做出決策,然後我們會修改行為樹。我們首先需要創建新的黑板鍵,這樣我們就能在行為樹上保存這些信息。打開」BB_EnenmyAI 「,在左側的「黑板」選項卡中,點擊「新建」按鈕,選擇「對象」類型,將這個新建命名為「Target Actor」。在右側的「黑板詳細信息」面板中,在「鍵」分段中展開「鍵類型」選項,在「基類」下拉菜單中將類型從「object」改為「Actor」。回到「黑板」面板,再次點擊「新建」,這次選擇布爾類型,把這個黑板鍵命名為「Has Line Of Sight」。
接下來,首先在內容瀏覽器中找到「AIC ThirPerson Character」然後打開它,接着創建一些輔助函數以便讓黑板鍵處理起來更加容易。第一個函數有一個Actor輸入,並會把某個黑板鍵設置為相同的Actor值,在「我的藍圖」面板中點擊「函數」分段中的加號圖標,新建一個函數,將函數命名為「Update Target Actor Key」。在細節面板中,點擊「輸入」分段中的加號,新建一個輸入,選擇「Actor」作為輸入類型,將此輸入命名為「Target Actor」。第一步是獲取當前的黑板。右鍵事件圖表,搜索「Get Blackboard」,選擇「AI」>「變量」中的「Get Blackboard」。拖動「黑板」組件對象引用的引腳然後輸入「Set value as Object」,這樣會自動把黑板對象作為「Set value as Object」的目標參數。接下來,我們需要創建一個鍵名,它指向與行為樹相關聯的黑板中的黑板鍵。為此,我們拖動「Set value as Object」的「key name」,選擇提升至變量,將這個新變量命名為「Target Actor Name」。保持選中狀態,移到細節面板,找到類別面板,新建一個類別,在這個選項框中輸入「Key Names」並以此命名。注意,這樣會把我們的新變量自動歸類到「我的藍圖」面板中的「Keys Names」類型。下一步是設置「Target Actor Name」的默認值,在此之前,我們需要編譯藍圖。

編譯後細節面板中「Target Actor Name」的默認值為無,將其設置為與黑板鍵名相同,即「Target Actor」。「Set value as Object」需要的最後一個參數就是傳遞給黑板的數值。這裡就要用到我們此前創建的輸入。將「Target Actor」連到「set values as object」的「object value」,把這個函數的執行引腳連到「Set value as Object」。
我們要創建的下一個函數擁有一個黑板鍵,它能保存AI當前能否通過感知系統觀察到玩家。和之前一樣,先在「我的藍圖」面板中新建一個函數,將它命名為「UpdateHasLineOfSightKey」,在細節面板的「輸入」分段中,點擊加號添加新的輸入,確保這個輸入是布爾類型,將這個新參數命名為「HasLineOfSight」。和之前的函數一樣,我們首先要獲得正確的黑板,右鍵點擊事件圖表,然後輸入「Get Blackboard」,選擇「AI」>」變量」中的函數,拖動這個黑板引用的引腳,然後輸入「Set value as Bool」,拖動「Key name」變量,選擇「提升為變量」,將其命名為「HasLineOfSightName」。 下一步是設置「HasLineOfSightName」的默認值,在此之前,我們需要編譯藍圖。編譯後細節面板中「HasLineOfSightName」的默認值為無,將其設置為與黑板鍵名相同,即Has Line Of Sight」。然後將兩個函數引腳相連,將「Has Line Of Sight」輸入引腳與「bool value」相連。
現在我們要回到角色的「on target perception updated」事件,然後使用這個時間來更新我們新建的黑板鍵。這意味着每當感知狀態發生改變時,相關的黑板鍵也會更新。
在內容瀏覽器中找到「AICharacter1」,首先在觸發「target lost」事件時,清空「target actor」黑板鍵。當前,這個事件會在目標超出視野5秒後觸發,這表示AI完全遺忘了目標Actor,並放棄進行跟蹤。為了訪問我們剛剛創建的函數,我們首先要獲取AI控制器的引用。右鍵點擊事件圖表,然後輸入「Get Controller」,直到出現這個函數,這個函數會返回一個泛型控制器引用。我們需要將這個泛型類型轉換為「AIC ThirdPerson Character」。為此,我們可以拖動返回值,輸入「Cast」,選擇「Cast to AIC ThirdPerson Character」。為了保證圖表條理清晰便於理解,我們可以轉換成純類型轉換,右鍵點擊節點選擇「轉換為純類型轉換」。現在拖動「AIC ThirdPerson Character」引腳然後引用我們定義的函數即「Update Target Actor Key」,然後連接設置節點的執行引腳,如圖所示:

此時,期望的黑板狀態是讓「target actor」的值為空,也就是現在沒有target actor。為此,這個函數不需要提供任何參數。
讓我們來看這個事件的另一種結果。我們需要使用「」line of sight」鍵來表示這種情況,我們利用函數把「HasLineOfSight」鍵設置為假,我們可以複製這兩個節點「Get Controller」和「Cast to AIC ThirdPerson Character」,他們允許我們獲得「AIC ThirdPerson Character」AI控制器。再次拖動「AIC ThirdPerson Character」引腳然後引用我們定義的函數即「update has line if sight key」, 然後連接設置節點的執行引腳,如圖所示:

複製這三個節點「Get Controller」和「Cast to AIC ThirdPerson Character」和「Update Target Actor Key」,將他們的執行節點連接到「clear and invalidate timer by handle「。這個句柄當前連到分支的」真「值引腳,這種情況下我們需要提供」target actor「。所幸我們之前已經設置好了,找到」我的藍圖「面板,找到」PerceivedActor「,按住Ctrl鍵,左鍵點擊它並拖到事件圖表中,將」PerceivedActor「連到」target Actor「。」PerceivedActor「是之前在事件中定義的變量,我們獲取了事件和感知系統提供的Actor,然後將」PerceivedActor「賦值給它,最後,複製上面這三個節點 「Get Controller」和「Cast to AIC ThirdPerson Character」和「update has line if sight key」,它們用於獲取「update has line of sight key「函數,將他們連接到「Update Target Actor Key」。注意,分支的這個部分用於定義Actor剛剛被感知系統被感知到時的狀態。這裡要把「has line of sight「設置為真,勾選函數中的複選框。
讓我們快速回顧一下做了那些修改。可以看到,這個「on target perception updated「事件為AI定義了三種不同狀態。第一種狀態,Actor被感知時,這個狀態定義了AI看到Actor時的情況。第二種結果,返回值為」假「的結果,定義了看不到Actor時的狀態。即使看不到,我們仍在黑板中保留了被感知Actor的值,這種狀態表示AI記得看到了某個對象,只是當前看不到了。最後是」target lost「事件,它會在對象消失5秒後觸發,這種狀態表示AI當前看不到,當前感知的Actor並且對它喪失了興趣。值得一提的是,我們之所以設置黑板鍵,就是為了提供信息,並通過黑板鍵將信息提供給行為,它不做任何決策,這由行為樹決定。
下面我們在行為樹中把所有這些修改內容拼合起來。我們將藉助新的黑板鍵和裝飾器,讓AI有能力決定是追逐玩家還是繼續隨機漫遊。首先,在內容瀏覽器中打開行為樹資源「BT_EnemyAI「,我們將使用當前保存在黑板中的信息,在兩個序列中二選一。刪除第一個序列,拖動根節點,在菜單中選擇」選擇器「,把選擇器連至現在的」隨機漫遊「序列。隨機漫遊序列的優先級比我們創建的序列要低。在行為樹中執行順序是從左到右。通過剛剛創建的選擇器新建一個序列,在細節面板中的」描述「分段中,將節點名稱改為」chase player「,拖動」chase player「序列,選擇」move to task「,我們需要將AI移到目標Actor的位置,為此,在右側細節面板中的」黑板「分段點擊」黑板鍵「,在下拉菜單中選擇」Target Actor「。」Target Actor「是我們創建的用於和函數一起更新的黑板鍵。接着,再次拖動追逐玩家序列,在」move to「節點的右側新建一個節點,選擇」Wait「節點,在細節面板的」等待「分段中,將等待時間五秒改為一秒。通常在任務結束後會添加一些等待任務,因為這能避免行為樹在不同序列間快速循環,從而顯得不自然。添加這兩個序列後,」追逐玩家「序列基本完成了,考慮到行為樹的執行順序,這個新的分支會始終在隨機漫遊序列之前執行。

接下來,需要使用裝飾器控制這個分支的執行方式,只有當前需要設置目標Actor時才執行它。右鍵點擊,」追逐玩家「序列,選擇」添加裝飾器「>」黑板「。接下來,選中這個新的裝飾器,在細節面板中的描述段將節點名稱改為」is a target actor set「。我們來看看要使用哪些黑板鍵,由於我們關心的是目標Actor,所以應該在細節面板中」黑板「分段中,在」黑板鍵「下拉菜單中選中」SetActor「。接下來我們需要思考的是和鍵有關的是什麼內容。」黑板「分段允許我們定義我們期望的結果。上面的」流程控制「分段允許我們控制觀察到期望結果時執行流程會發生什麼。」通知觀察者「下拉菜單有兩個選項,默認選項是」on result change「。每當鍵查詢的結果發生變化時,我們會按照」observer aborts「描述的內容更改執行流程。



