UE學(xué)習(xí)記錄:AI

今天要討論Unreal中的AI系統(tǒng),包括以下幾個(gè)部分:
首先是NavigationMesh,它僅為我們的AI角色提供尋路數(shù)據(jù),而且它基本上只是告訴AI他可以和不允許移動(dòng)的地方。
然后是BehaviorTree(行為樹 ),它基本上是AI的大腦,把它想象成一個(gè)基于節(jié)點(diǎn)的樹,從上到下,從左到右執(zhí)行,這是我們今天主要關(guān)注的內(nèi)容。
還有BlackBoard,為AI提供數(shù)據(jù)存儲(chǔ),可以理解為AI的記憶,本身不運(yùn)行任何邏輯。
環(huán)境查詢系統(tǒng)EnvironmentQuerySystem,為AI進(jìn)行空間查詢,以弄清世界中靠近AI的物體,甚至是世界中一些適合做掩護(hù)的地方。
PawnSensing & AIPerception,為AI中加入類似于感覺的東西,比如說能夠看到或聽到玩家的聲音。
還有兩個(gè)調(diào)試工具,GameplayDebugger(游戲調(diào)試器)和VisualLogger(視覺記錄器)。
對于行為樹BehaviorTree。首先有個(gè)結(jié)點(diǎn)叫Sequence,它負(fù)責(zé)從上到下,從左到右按順序運(yùn)行,并取消“失敗”的節(jié)點(diǎn);然后是Selector,它將從左往右依次選擇他的孩子節(jié)點(diǎn)。我們有三種方法來裝飾BehaviorTree
task(比如Wait,MoveTo),它可以在多秒或多幀中被執(zhí)行,比如這里的執(zhí)行Wait 0.8秒,執(zhí)行MoveTo直到抵達(dá)目的地。
Service,它會(huì)反復(fù)執(zhí)行后臺(tái)任務(wù),像是這里的“Cancel others when in attack range”,重復(fù)對AI下指令以更新它的狀態(tài)。
Decorator,它基本上是用于狀態(tài)檢查和流控制,返回true/false,比如這里的Cooldown節(jié)點(diǎn),第一次觸發(fā)這個(gè)節(jié)點(diǎn)它將被允許運(yùn)行,而在第二次觸發(fā)的時(shí)候如果冷卻時(shí)間(Wait)沒到,就不能運(yùn)行,將會(huì)執(zhí)行MoveTo。

由于每當(dāng)我們添加一個(gè)新的類,編輯器就會(huì)試圖進(jìn)行熱重載,所以在這里進(jìn)行設(shè)置以解決這個(gè)麻煩,進(jìn)入編輯器,編輯->編輯器偏好設(shè)置->所有設(shè)置->熱重載->取消勾選

首先我們添加一個(gè)Character類,命名為RgAICharacter,可以刪除這個(gè)類的組件綁定部分;再添加一個(gè)AIController類,命名為RgAIController,我們會(huì)將AI的行為寫到AIController類中。在編輯器中創(chuàng)建一個(gè)AI的文件夾,在里面創(chuàng)建一個(gè)RgAICharacter類的藍(lán)圖,命名為BP_MinionRanged,設(shè)置Mesh和動(dòng)畫后把AI放到場景中。添加導(dǎo)航網(wǎng)格數(shù)據(jù),它可以使得AI在碰到障礙物時(shí)能夠調(diào)整移動(dòng),我們在左邊的放置Actor一欄搜索nav?mesh?bounds volum,把它拖進(jìn)場景,如果它不可見,可以在顯示中勾選導(dǎo)航或者按P鍵。
右鍵->人工智能->行為樹,命名為BT_MinionRanged;右鍵->人工智能->黑板,命名為BB_MinionRanged。在黑板中我們可以選擇我們想保留的數(shù)據(jù),然后在行為樹中我們可以制作執(zhí)行邏輯。在行為樹中指定使用的黑板,然后到黑板中添加數(shù)據(jù),我們添加一個(gè)向量類型的新鍵,命名為MoveToLocation,然后到行為樹中執(zhí)行實(shí)際的移動(dòng),我們從根的下拉列表里選擇Sequence,在Sequence下拉列表的tasks中選擇MoveTo(MoveDirectlyToward會(huì)忽略導(dǎo)航),細(xì)節(jié)->背景->黑板鍵,選擇MoveToLocation,這樣就為行為樹分配了黑板來使用MoveTo了。另外,在Sequence下拉列表的tasks中選擇Wait,這樣在MoveTo執(zhí)行完后,可以等待設(shè)定時(shí)間,默認(rèn)設(shè)置為5s。
現(xiàn)在我們可以進(jìn)入RgAIController類中實(shí)現(xiàn)MoveTo的邏輯。首先我們重寫B(tài)eginPlay,調(diào)用Super確保其基本的邏輯。然后,我們調(diào)用包含在AIController中的RunBehaviorTree,這里指定的UBehaviorTree*是一個(gè)變量,我們把它變成一個(gè)資產(chǎn),暴露給藍(lán)圖:
在編輯器中創(chuàng)建RgAIController類的藍(lán)圖,命名為BP_MinionController,AI設(shè)置里的行為樹選擇BT_MinionRanged,然后到AI角色藍(lán)圖里,細(xì)節(jié)->Pawn->AI控制器類,選擇BP_MinionController,這就是它實(shí)際上將產(chǎn)生的類,打開行為樹BT_MinionRanged,模擬運(yùn)行就能看到它的執(zhí)行情況,所有的步驟都是執(zhí)行的,但目前AI角色沒有移動(dòng),是因?yàn)檫€沒有設(shè)置MoveToLocation的值,我們到RgAIController.cpp中添加如下代碼:
這樣一來AI就會(huì)走到玩家出生的地方,但AI只會(huì)移動(dòng)一次,玩家離開出生點(diǎn)后AI并不會(huì)繼續(xù)追蹤玩家,這是由于MoveToLocation在玩家生成時(shí),只被賦值了一次,所以行為樹每次更新MoveTo獲取的MoveToLocation都是同一個(gè)數(shù)值。要實(shí)時(shí)追蹤玩家的位置,首先進(jìn)入黑板,添加object類型的新鍵命名為TargetActor,指定它的基類為Actor,并在行為樹的MoveTo中將原來的黑板鍵MoveToLocation指定為TargetActor,然后到RgAIController.cpp中為其進(jìn)行設(shè)置。
游戲運(yùn)行時(shí),按下“;”鍵可以打開游戲調(diào)試器,我們可以看到相關(guān)的信息,比如人物類別,控制器實(shí)例,行為樹,當(dāng)行為樹足夠復(fù)雜的時(shí)候,我們可以對節(jié)點(diǎn)進(jìn)行自定義注釋或者命名,可以使其在調(diào)試的時(shí)候更容易閱讀。