斯坦福UE4C++課程P39-P41基礎(chǔ)AI與行為樹
首先介紹AI基本概念:行為樹、黑板、EQS
行為樹是UE中AI做出選擇的依據(jù),其他AI系統(tǒng)還有utility AI和gope。
對于虛幻AI系統(tǒng):
Navigation Mesh:Provides data on where AI is allowed to move (Path Finding)
Behavior Tree:'Brains' of AI. Tree executing from top-to-bottom and left-to-right
Selector,Sequence
Task,Service,Decorator
Blackboard:‘Memory’ of AI. Data storage,no logic
Environment Query System:Spatial queries for finding objects/locations based on 'tests'
PawnSensing & AIPerception:'Senses' to see or hear others
Debugging Tools
Gameplay Debugger (in-game:撇號鍵)
Visual Logger (Window > Developer Tools > Visual Logger)
Selector:從左至右選擇一個子節(jié)點執(zhí)行(先檢查裝飾器Decorator看是否能夠執(zhí)行)
Sequence:從左至右執(zhí)行一系列子節(jié)點(cancel sequence on any ‘failure’)
Task,Service,Decorator:Task是AI動作(比如attack、move to...),Service重復(fù)執(zhí)行背景任務(wù)(background tasks),Decorator裝飾器可以用來檢查條件、流程控制(返回true/false)
行為樹節(jié)點:
接下來我們新建一個character類和AIController類,放在public/AI文件夾下。
AIController類類似于AI的大腦,我們將添加行為樹到AIController類中
在AIController中添加行為樹組件
在BeginPlay函數(shù)中:
運行行為樹之后,我們獲取到當(dāng)前游戲編號為0的Pawn角色,把黑板的名為MoveToLocation的鍵賦值為Pawn的位置。
tip:有的函數(shù)第一個參數(shù)是const UObject* WorldContextObject,因為這是在靜態(tài)類中的函數(shù),沒有上下文,需要傳進(jìn)去一個指定它在哪里被調(diào)用的對象,一般用this就行。
接下來在UE編輯器創(chuàng)建好AI角色藍(lán)圖、行為樹、黑板、繼承自新建C++AIController的AI控制器藍(lán)圖。
現(xiàn)在運行游戲,AI會移動到玩家出生點位置。
下面在黑板新建一個Object,父類選為Actor,命名TargetActor。行為樹的MoveTo節(jié)點換為TargetActor。由于MoveTo節(jié)點每幀調(diào)用, 所以AI將一致追尋玩家,直到追到為止。我們在C++的BeginPlay函數(shù)中添加
將TargetActor鍵綁定為玩家。
現(xiàn)在編譯運行游戲,AI追尋玩家直到追到為止。

當(dāng)MoveTo節(jié)點執(zhí)行完畢后,將執(zhí)行Wait5秒,然后返回行為樹的Root,重新執(zhí)行MoveTo。
tip:可以使用回車鍵左邊的撇號鍵在游戲運行時開啟Debug界面


現(xiàn)在我們想讓AI只有距離玩家有限范圍時才追尋玩家
我們使用BTService繼承的C++類SBTService_CheckAttackRange。
使用父類的TickNode函數(shù)?,F(xiàn)在直接編譯,會報無法解析符號的錯,解決辦法是到項目構(gòu)建文件ActionRogueLike.Build.cs里添加‘GameplayTasks’模塊。另外,在.uproject文件我們看到‘AIModule’模塊已經(jīng)被加入到項目,但為了保險起見,我們把該模塊也加入到.cs文件里。
現(xiàn)在編譯通過。
.h文件,新建了一個黑板鍵選擇器和TickNode函數(shù)
.cpp文件,檢查目標(biāo)actor是否在AI的2000距離范圍內(nèi),來決定是否要追尋玩家
現(xiàn)在編譯,回到黑板新建WithinAttackRange布爾變量,保存,在行為樹MoveToSequence節(jié)點右鍵選擇Add Service,選擇CheckAttackRange。
給Move To Player節(jié)點添加裝飾器,類型選擇Blackboard,鍵選擇WithinAttackRange。

根據(jù)我們的需求,調(diào)整節(jié)點如下:

selector節(jié)點從左到右檢查能夠執(zhí)行的首個節(jié)點來執(zhí)行
現(xiàn)在只要玩家在范圍內(nèi),就會一直移動到玩家位置(不會向右執(zhí)行了),否則等待5秒后返回根節(jié)點root繼續(xù)判斷。
我們點擊裝飾器,把observer aborts選為self,表示當(dāng)條件改為true時,將中止裝飾器所在節(jié)點及所有子節(jié)點的執(zhí)行,返回false,selector執(zhí)行wait,當(dāng)玩家再次不在范圍時,條件變?yōu)閠rue,selector繼續(xù)執(zhí)行move to player。
所以現(xiàn)在的效果是,AI移動到離玩家2000距離就會停止。

現(xiàn)在,只根據(jù)距離來判斷讓AI過于強大,因為如果AI和玩家隔了一堵墻,在根本看不見玩家的情況下仍可以追尋玩家,所以我們給AI添加視線追蹤。
現(xiàn)在,如果AI看不到玩家,就算在范圍內(nèi),仍會追尋玩家直到有視線為止。