最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

TomLooman_ActionRoguelike_第十章基礎(chǔ)AI與行為樹

2023-08-11 17:42 作者:別叫我小紅  | 我要投稿

該專欄用于保存對(duì)TomLooman的ActionRoguelike項(xiàng)目的學(xué)習(xí)筆記,學(xué)習(xí)過程中的思考與記錄不一定準(zhǔn)確。


教程參考:https://github.com/tomlooman/ActionRoguelike

基于UE5.0的項(xiàng)目實(shí)現(xiàn):https://github.com/CarolBaggins2023/TomLooman_ActionRoguelike_Tutorial

2023_08_08

基礎(chǔ)AI與行為樹:機(jī)器人的行為和運(yùn)動(dòng),自定義檢查攻擊范圍的行為樹服務(wù)

?

AI機(jī)器人類似于玩家控制的角色,不同的是它受到AIController的控制,因此要?jiǎng)?chuàng)建AI機(jī)器人,我們創(chuàng)建一個(gè)Character類和一個(gè)AIController類。

SAICharacter與之前創(chuàng)建的SCharacter類似,但不需要實(shí)現(xiàn)SetupPlayerInputComponent函數(shù),因?yàn)锳I機(jī)器人不需要玩家的輸入。

不同的是,在SAICharacter的藍(lán)圖子類中,我們要將自己創(chuàng)建的AIController藍(lán)圖子類賦值給AI Controller Class。

在AIController中,我們可以通過RunBehaviorTree執(zhí)行行為樹來控制機(jī)器人的行為,為此我們需要先在AIController類中聲明一個(gè)行為樹變量,然后在編輯器中賦值。

?

我們可以如下創(chuàng)建自己的行為樹和黑板,其中行為樹控制對(duì)象行為邏輯,黑板則保存行為樹中要用到的數(shù)據(jù)。

在行為樹中,我們可以將黑板賦給行為樹,這樣就能在行為樹中使用黑板存儲(chǔ)的數(shù)據(jù)。

我們先制作如下的簡(jiǎn)單行為樹,其中Sequence節(jié)點(diǎn)從左至右順序執(zhí)行其子節(jié)點(diǎn),但執(zhí)行完所有子節(jié)點(diǎn)或者某個(gè)子節(jié)點(diǎn)失敗時(shí)停止。MoveTo節(jié)點(diǎn)使用導(dǎo)航系統(tǒng)移動(dòng)到某個(gè)位置或Actor,由黑板中的變量決定。

我們創(chuàng)建了一個(gè)行為樹后,還要將其賦值給AIController的行為樹成員變量,這樣才能通過AIController控制機(jī)器人執(zhí)行該行為樹。

所以,AICharacter、AIController、行為樹、黑板之間的關(guān)系是,AICharacter的行為受AIController控制,AIController可以擁有行為樹成員變量,并讓AICharacter執(zhí)行行為樹,行為樹擁有黑板,可以使用黑板中的數(shù)據(jù)。

另外,要讓機(jī)器人運(yùn)動(dòng),我們要給機(jī)器人劃定導(dǎo)航網(wǎng)格(可能是因?yàn)轭愃芃oveTo的行為用到了導(dǎo)航網(wǎng)格),也就是下圖中的綠色區(qū)域,我們?cè)赑laceActor中可以放置導(dǎo)航網(wǎng)格,并在世界中對(duì)導(dǎo)航網(wǎng)格進(jìn)行放大和縮小。

?

上面的行為樹暫時(shí)還無法執(zhí)行,因?yàn)槲覀冊(cè)贛oveTo節(jié)點(diǎn)用到了黑板中的Vector變量MoveToLoaction,當(dāng)現(xiàn)在還沒人給這個(gè)變量賦值。那么我們就應(yīng)該在某個(gè)地方給這個(gè)變量賦值,我們?cè)贏IController中執(zhí)行這一步操作(可能是因?yàn)樾袨闃涫茿IController的成員變量,被它直接調(diào)用)。

不要被下面的代碼誤導(dǎo),我們并不是通過機(jī)器人的Pawn來訪問行為樹的黑板,這里的MyPawn只是為了獲得玩家的位置,然后將位置值賦給黑板中的變量。我們也不需要先訪問行為樹成員變量,再訪問行為樹的黑板,而是可以通過GetBlackboardComponent直接訪問黑板,并用SetValueAsXXX給黑板中某個(gè)類型的變量賦值。

除了向上面那樣用MoveTo節(jié)點(diǎn)讓機(jī)器人移動(dòng)到某個(gè)具體位置之外,我們還可以讓機(jī)器人移動(dòng)到某個(gè)Actor,實(shí)現(xiàn)方式類似。當(dāng)然,此時(shí)黑板中要存在一個(gè)Actor類型的變量,

?

當(dāng)我們測(cè)試機(jī)器人時(shí),有兩種方法,可以結(jié)合使用。

第一種是直接看行為樹的執(zhí)行流,以及黑板中的變量,跟測(cè)試藍(lán)圖類似,

第二種是運(yùn)行時(shí)按引號(hào)鍵,使用GameplayDebugger,

為了讓信息在Gameplay調(diào)試器中更加易讀,我們可以在行為樹中修改節(jié)點(diǎn)的名字,

當(dāng)世界中有兩個(gè)機(jī)器人時(shí),按下引號(hào)鍵時(shí)會(huì)顯示處于屏幕中心的機(jī)器人的信息。

?

因?yàn)槲覀兿M麢C(jī)器人是遠(yuǎn)程單位,能夠在距離角色一定距離的地方停下,所以我們對(duì)行為樹進(jìn)行如下修改,

其中的Selector節(jié)點(diǎn)不同于Sequence節(jié)點(diǎn),它不會(huì)順序執(zhí)行所有子節(jié)點(diǎn),而是只執(zhí)行第一個(gè)為true的子節(jié)點(diǎn),所以配合Blackboard節(jié)點(diǎn)使用。Blackboard節(jié)點(diǎn)會(huì)檢查給定的黑板鍵,也就是黑板中的變量,是否設(shè)置了值,類似于檢查空值的if語(yǔ)句。

這里Blackboard節(jié)點(diǎn)檢查黑板中一個(gè)名為bWithinAttackRange的bool變量是否為false,這變量表示玩家是否在機(jī)器人的射程內(nèi)。那么從邏輯上來說,在機(jī)器人運(yùn)行過程中,應(yīng)該會(huì)有一個(gè)函數(shù),在每個(gè)Tick計(jì)算機(jī)器人與玩家的距離,并與機(jī)器人的射程比較。

要實(shí)現(xiàn)這樣的Tick效果,我們可以使用行為樹中的Service(服務(wù))節(jié)點(diǎn)。Service節(jié)點(diǎn)的特點(diǎn)是,當(dāng)其分支被執(zhí)行,節(jié)點(diǎn)就會(huì)以一定頻率執(zhí)行,這些節(jié)點(diǎn)常用于檢查和更新黑板。

我們可以通過Add Service添加Service節(jié)點(diǎn),Service節(jié)點(diǎn)具體的執(zhí)行內(nèi)容由我們自己定義。我們可以創(chuàng)建行為樹Service節(jié)點(diǎn)類,并實(shí)現(xiàn)其中的TickNode成員函數(shù)。

?

TickNode的實(shí)現(xiàn)如下。

我們從想求的目標(biāo)出發(fā)思考實(shí)現(xiàn)中需要得到哪些東西。我們最終需要得到一個(gè)bool值,這個(gè)bool值表示玩家是否在機(jī)器人的攻擊范圍內(nèi)。為了得到這個(gè)bool值,我們需要求得機(jī)器人與玩家之間的距離,那么就需要得到指向玩家和機(jī)器人的指針。

(在以下邏輯中要注意,我們的Service節(jié)點(diǎn)是附著在行為樹上的,所以能直接訪問到的是行為樹。而且和使用行為樹的AIController不同,Service節(jié)點(diǎn)不能直接訪問黑板。)

然后再來看這個(gè)函數(shù)的實(shí)現(xiàn)。先考慮怎么獲得玩家的指針,回想我們這個(gè)行為樹的邏輯,機(jī)器人在離玩家一定距離時(shí)停下,所以有一個(gè)MoveTo(TargetActor)的節(jié)點(diǎn),那么黑板中也就必然有一個(gè)TargetActor對(duì)象(在AIController的構(gòu)造函數(shù)中賦值),那么我們就可以通過訪問黑板來得到指向玩家的指針。因此,我們先通過OwnerComp.GetBlackboardComponent

得到黑板組件,OwnerComp是行為樹的引用。再通過BlackboardComp->GetValueAsObject("TargetActor")得到黑板中的TargetActor變量,也就是指向玩家的指針,因?yàn)镚etValueAsObject,返回的是UObject類型的指針,所以還需要進(jìn)行Cast。

然后我們要考慮怎么獲取指向機(jī)器人的指針,我們現(xiàn)在能訪問到行為樹組件,而行為樹組件又被AIController擁有,所以我們能訪問AIController,而AIController又直接控制著機(jī)器人,這樣我們就能訪問到機(jī)器人了。因此,我們先通過OwnerComp.GetAIOwner得到AIController,再通過AIController->GetPawn得到AIController控制的機(jī)器人。

得到玩家和機(jī)器人后,通過FVector::Distance就能得到兩者在世界中的距離,并與表示機(jī)器人攻擊距離的Service節(jié)點(diǎn)類的成員變量作比較,得到想求的bool值。

我們又在上面的基礎(chǔ)之上多做了一步。因?yàn)橛袝r(shí)即使玩家和機(jī)器人距離很近,但是要是隔著一堵墻,機(jī)器人實(shí)際上也無法攻擊到玩家,所以最后返回的bool值應(yīng)該是上面距離的bool與“機(jī)器人能否看到玩家”的與邏輯(這里先不考慮空氣墻的情況)。通過AIController->LineOfSightTo(TargetActor)我們可以得到“機(jī)器人能否看到玩家”的結(jié)果。

最終,我們通過BlackboardComp->SetValueAsBool(AttackRangeKey.SelectedKeyName, bWithinRange && bCanSee);對(duì)黑板中的變量進(jìn)行賦值。其中,AttackRangeKey.SelectedKeyName可以用硬編碼,也就是距離的變量名替代,也可以創(chuàng)建FName類型的成員變量。推薦的是像這里一樣在Service節(jié)點(diǎn)類中創(chuàng)建一個(gè)黑板條目類型的成員變量,然后在行為樹的具體Service節(jié)點(diǎn)中與黑板中的變量進(jìn)行綁定。

?

在上述代碼的編譯中會(huì)遇到一個(gè)unresolved external symbol報(bào)錯(cuò),具體原因沒聽明白。解決這個(gè)報(bào)錯(cuò),要在Build.cs中進(jìn)行修改。具體看教程。

?

我們希望當(dāng)玩家遠(yuǎn)離機(jī)器人時(shí),機(jī)器人會(huì)立刻接近玩家,而不是執(zhí)行Wait節(jié)點(diǎn)5s,再去接近玩家。也就是說,當(dāng)判斷距離的bool變量改變時(shí),應(yīng)該中斷當(dāng)前節(jié)點(diǎn)的任務(wù),重新執(zhí)行父節(jié)點(diǎn)。

之前我們提到Blackboard節(jié)點(diǎn)類似于一個(gè)if函數(shù),它能判斷黑板的某個(gè)變量是否為空。Blackboard節(jié)點(diǎn)中的ObserverAborts參數(shù)還可以用來控制中斷,在ObserverAborts不是None時(shí),Blackboard節(jié)點(diǎn)將監(jiān)聽行為樹中的其它任務(wù)。當(dāng)Blackboard節(jié)點(diǎn)判斷為true時(shí),觸發(fā)ObserverAborts參數(shù)規(guī)定的中斷類型,中斷行為樹中的任務(wù),并執(zhí)行更高優(yōu)先級(jí)的任務(wù)。

中斷類型包括Self,LowerPriority和Both。當(dāng)值為Self時(shí),Blackboard節(jié)點(diǎn)會(huì)監(jiān)聽自己這棵子樹,當(dāng)中斷條件被滿足時(shí),中斷自身。當(dāng)值為L(zhǎng)owerPriority時(shí),Blackboard節(jié)點(diǎn)監(jiān)聽比自己優(yōu)先級(jí)低的子樹,當(dāng)中斷條件被滿足時(shí),會(huì)中斷這個(gè)優(yōu)先級(jí)更低的節(jié)點(diǎn)。Both則會(huì)同時(shí)監(jiān)聽并中斷自身和優(yōu)先級(jí)更低的節(jié)點(diǎn)。

節(jié)點(diǎn)的優(yōu)先級(jí)同時(shí)由節(jié)點(diǎn)類型、條件判斷和ObserverAborts參數(shù)的設(shè)置決定。深度越深的節(jié)點(diǎn),優(yōu)先級(jí)越低。這里因?yàn)闂l件判斷和ObserverAborts參數(shù)的原因,左節(jié)點(diǎn)比右節(jié)點(diǎn)的優(yōu)先級(jí)高。


TomLooman_ActionRoguelike_第十章基礎(chǔ)AI與行為樹的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
南乐县| 水城县| 泸定县| 滨州市| 涞水县| 镇坪县| 遂平县| 天台县| 元阳县| 广饶县| 蓝田县| 中方县| 治县。| 杭锦后旗| 苍梧县| 介休市| 莱州市| 上林县| 普兰店市| 河东区| 岚皋县| 天祝| 东乡县| 维西| 曲阜市| 南皮县| 泸定县| 信阳市| 麻城市| 尚义县| 兴义市| 浏阳市| 丰顺县| 松原市| 丰城市| 隆子县| 全南县| 葫芦岛市| 无极县| 日喀则市| 佛学|