原文:Unreal Engine 4 Tutorial: Artificial Intelligence
作者:Tommy Tran
譯者:Shuchang Liu
在本篇教程中,你將學(xué)習(xí)如何使用行為樹和AI感知來創(chuàng)建一個(gè)能四處走動(dòng)呼渣,攻擊敵人的簡單AI早敬。
在視頻游戲中,人工智能(AI)通常指的是擁有自主決策行為的非玩家角色沉唠。AI可以是看到玩家然后進(jìn)行攻擊的簡單角色疆虚,也可以是即時(shí)策略(RTS)游戲里的強(qiáng)大對(duì)手。
在Unreal引擎里满葛,我們可以通過行為樹創(chuàng)建AI径簿。行為樹是一個(gè)決定AI做哪種行為的實(shí)時(shí)決策系統(tǒng)。比如嘀韧,如果AI有戰(zhàn)斗和逃跑兩種行為篇亭。你可以創(chuàng)建行為樹,讓AI在高于50%血量時(shí)進(jìn)行戰(zhàn)斗锄贷,低于50%血量時(shí)逃跑暗赶。
在本篇教程中鄙币,你將學(xué)習(xí)到:
創(chuàng)建AI實(shí)體用于控制角色單位
創(chuàng)建并使用行為樹和黑板
使用AI感知讓角色單位獲得視野
-
創(chuàng)建行為讓角色單位四處走動(dòng)并攻擊敵人
注意:本篇教程只是Unreal Engine 4系列教程的其中一篇:
起步入門
下載示例項(xiàng)目并解壓。進(jìn)入項(xiàng)目文件夾蹂随,雙擊MuffinWar.uproject打開項(xiàng)目十嘿。
按下Play運(yùn)行游戲,在圍欄內(nèi)點(diǎn)擊左鍵生成蘑菇小人绩衷。
在本例中激率,我們將創(chuàng)建一個(gè)能四處走動(dòng)的AI嘉冒,當(dāng)其他蘑菇小人進(jìn)入AI的視野時(shí)顶籽,AI會(huì)追逐對(duì)方并進(jìn)行攻擊。
要?jiǎng)?chuàng)建一個(gè)AI角色银觅,我們需要三個(gè)元素:
- 身體:這個(gè)是角色的物理表現(xiàn)礼饱,在本例中,蘑菇小人就是身體
- 靈魂:這個(gè)是控制角色行為的實(shí)體究驴,既能是玩家本身镊绪,也可以是AI
- 大腦: AI進(jìn)行決策行為的邏輯,我們可以用C++代碼洒忧,藍(lán)圖或者是行為樹來實(shí)現(xiàn)邏輯蝴韭。
現(xiàn)在我們已經(jīng)有了身體,接著要搞來靈魂和大腦跑慕。首先,我們要?jiǎng)?chuàng)建控制器作為靈魂摧找。
什么是控制器核行?
控制器是一個(gè)能控制角色單位的非物理Actor。這里所說的“控制”蹬耘,具體指的是什么意思呢芝雪?
對(duì)于玩家而言,控制指的是能通過按鍵操控角色單位综苔〕拖担控制器獲取玩家輸入位岔,并將輸入直接傳給角色。當(dāng)然堡牡,控制器也可以獲取輸入進(jìn)行處理抒抬,然后再告訴角色單位做哪個(gè)行為。
對(duì)于AI來說晤柄,角色單位就是由控制器或“大腦”(取決于實(shí)現(xiàn)方式)來通知其做什么行為的擦剑。
為了用AI控制蘑菇小人,我們需要?jiǎng)?chuàng)建一類特殊的控制器——AI控制器芥颈。
創(chuàng)建AI控制器
打開Characters\Muffin\AI目錄并創(chuàng)建Blueprint Class惠勒,選中AIController作為父類并命名為AIC_Muffin。
接著爬坑,我們需要讓蘑菇小人使用這個(gè)AI控制器纠屋,打開Characters\Muffin\Blueprints并雙擊打開BP_Muffin。
默認(rèn)情況下盾计,Details面板會(huì)顯示藍(lán)圖的默認(rèn)設(shè)置售担,如果沒有顯示,就點(diǎn)擊Toolbar的Class Defaults闯估。
在Details面板找到Pawn設(shè)置灼舍,將AI Controller Class設(shè)為AIC_Muffin,這樣當(dāng)蘑菇小人生成時(shí)涨薪,就會(huì)對(duì)應(yīng)生成一個(gè)AI控制器實(shí)例骑素。
由于我們要?jiǎng)討B(tài)生成蘑菇小人,Auto Possess AI要設(shè)成Spawned刚夺。這樣當(dāng)蘑菇小人生成時(shí)献丑,AIC_Muffin就會(huì)自動(dòng)控制BP_Muffin。
點(diǎn)擊Compile并關(guān)閉BP_Muffin侠姑。
現(xiàn)在创橄,我們要來創(chuàng)建決策蘑菇小人行為的邏輯,就要用上行為樹莽红。
創(chuàng)建行為樹
打開Characters\Muffin\AI目錄妥畏,并選擇Add New\Artificial Intelligence\Behavior Tree,將其命名為BT_Muffin并打開安吁。
行為樹編輯器
行為樹編輯器包含3個(gè)新面板:
- Behavior Tree:這個(gè)圖表面板用于創(chuàng)建行為樹節(jié)點(diǎn)
- Details:展示選中節(jié)點(diǎn)的參數(shù)
- Blackboard:展示黑板的所有鍵值(后續(xù)講解)和其對(duì)應(yīng)數(shù)值醉蚁。只有在游戲運(yùn)行時(shí)才會(huì)有顯示
像藍(lán)圖一樣,行為樹也是由節(jié)點(diǎn)構(gòu)成的鬼店。行為樹有4類節(jié)點(diǎn)网棍,前兩種分別是任務(wù)(tasks)和組合(composites)節(jié)點(diǎn)。
什么是任務(wù)和組合節(jié)點(diǎn)妇智?
顧名思義滥玷,任務(wù)節(jié)點(diǎn)負(fù)責(zé)完成具體任務(wù)氏身,可以是表現(xiàn)一套連招這樣的復(fù)雜任務(wù),也可以是原地等待這樣的簡單任務(wù)惑畴。
要完成多個(gè)任務(wù)蛋欣,我們就要用上組合節(jié)點(diǎn)。一個(gè)行為樹由許多分支(行為)組成桨菜。每個(gè)分支的根節(jié)點(diǎn)豁状,都是一個(gè)組合節(jié)點(diǎn)。不同類型的組合節(jié)點(diǎn)倒得,執(zhí)行其子節(jié)點(diǎn)的方式也各不相同泻红。
比如,我們有一組如下序列的行為:
要按順序執(zhí)行每個(gè)行為霞掺,我們就要用上Sequence組合節(jié)點(diǎn)谊路,因?yàn)镾equence節(jié)點(diǎn)能夠從左至右的執(zhí)行子節(jié)點(diǎn),圖表看起來是這樣的:
注意:從組合節(jié)點(diǎn)衍生出來的節(jié)點(diǎn)可以稱為子樹(subtree)菩彬。通常來說缠劝,這些節(jié)點(diǎn)就統(tǒng)稱為一個(gè)行為。比如骗灶,Sequence惨恭,Move To Enemy,Rotate Towards Enemy和Attack就統(tǒng)稱為“攻擊敵人”行為耙旦。
如果Sequence的任意節(jié)點(diǎn)執(zhí)行失敗脱羡,整個(gè)Sequence節(jié)點(diǎn)就會(huì)停止執(zhí)行。
比如免都,如果角色無法移動(dòng)到敵人身邊锉罐,Move To Enemy節(jié)點(diǎn)就執(zhí)行失敗了,這樣Rotate Towards Enemy和Attack節(jié)點(diǎn)也就無法繼續(xù)執(zhí)行了绕娘。反之脓规,如果角色成功移動(dòng)到敵人邊上,就能執(zhí)行隨后兩個(gè)節(jié)點(diǎn)险领。
后續(xù)我們還會(huì)學(xué)習(xí)Selector組合節(jié)點(diǎn)侨舆,不過現(xiàn)在先讓我們用Sequence節(jié)點(diǎn)實(shí)現(xiàn)角色隨機(jī)移動(dòng)到某個(gè)位置并原地停留。
隨機(jī)移動(dòng)位置
首先绢陌,創(chuàng)建Sequence節(jié)點(diǎn)并與Root節(jié)點(diǎn)相連挨下。
接著,我們需要讓角色移動(dòng)起來下面,創(chuàng)建MoveTo節(jié)點(diǎn)與Sequence節(jié)點(diǎn)相連复颈,這個(gè)節(jié)點(diǎn)可以驅(qū)動(dòng)角色移動(dòng)到特定位置或Actor绩聘。
隨后沥割,創(chuàng)建Wait節(jié)點(diǎn)與Sequence節(jié)點(diǎn)相連耗啦,確保將其放置在MoveTo節(jié)點(diǎn)右邊,放置順序非常重要机杜,因?yàn)樽庸?jié)點(diǎn)是按照從左到右的順序執(zhí)行的帜讲。
注意:你可以通過每個(gè)節(jié)點(diǎn)右上角的數(shù)字確認(rèn)其執(zhí)行順序。數(shù)字越小執(zhí)行順序越高椒拗。
恭喜你似将,你剛剛創(chuàng)建了你的第一個(gè)行為!它將會(huì)驅(qū)動(dòng)角色移動(dòng)到指定位置并原地停留數(shù)秒蚀苛。
為了讓角色移動(dòng)在验,我們還需要指定要移動(dòng)的位置。由于MoveTo節(jié)點(diǎn)只接受由黑板提供的數(shù)值堵未,我們要先創(chuàng)建一個(gè)黑板腋舌。
創(chuàng)建黑板
黑板是一個(gè)單純用來存放變量(鍵值)的資源。我們可以將其理解為AI的內(nèi)存渗蟹。
雖然黑板不是必須使用的块饺,但它確實(shí)為我們讀取,存取數(shù)據(jù)提供了極大便利雌芽,這么說的原因是很多行為樹節(jié)點(diǎn)只接受黑板鍵值作為參數(shù)輸入授艰。
要?jiǎng)?chuàng)建一個(gè)黑板,我們在Content Browser選擇新建Add New\Artificial Intelligence\Blackboard世落,將其命名為BB_Muffin并打開淮腾。
黑板編輯器
黑板編輯器由2個(gè)面板組成:
- Blackboard:展示所有鍵值列表
- Blackboard Details:展示所選鍵值的參數(shù)
現(xiàn)在,我們要?jiǎng)?chuàng)建一個(gè)鍵值用于存放目標(biāo)位置岛心。
創(chuàng)建目標(biāo)位置鍵值
由于是3D空間里的一個(gè)位置點(diǎn)来破,我們需要用Vector來進(jìn)行存儲(chǔ)。點(diǎn)擊New Key并選擇Vector忘古,將其命名為TargetLocation徘禁。
接著,我們需要隨機(jī)生成一個(gè)位置并將其存在黑板里髓堪,我們就需要用到第三種類型的行為樹節(jié)點(diǎn):服務(wù)(service)節(jié)點(diǎn)送朱。
什么是服務(wù)節(jié)點(diǎn)?
服務(wù)節(jié)點(diǎn)類似于任務(wù)節(jié)點(diǎn)干旁,用于完成一些事情驶沼。然而,不同于操控角色做特定行為争群,服務(wù)節(jié)點(diǎn)用于執(zhí)行檢查或更新黑板操作回怜。
服務(wù)并不是獨(dú)立節(jié)點(diǎn),而是依附于任務(wù)節(jié)點(diǎn)或者組合節(jié)點(diǎn)换薄。這樣使得行為樹更加簡潔易于組織玉雾,不會(huì)橫生太多節(jié)點(diǎn)翔试。如果我們用任務(wù)節(jié)點(diǎn)來實(shí)現(xiàn),效果如下圖所示:
如果用服務(wù)節(jié)點(diǎn)來實(shí)現(xiàn)复旬,則如下圖所示:
現(xiàn)在垦缅,讓我們來創(chuàng)建一個(gè)生成隨機(jī)位置的服務(wù)吧。
創(chuàng)建服務(wù)
回到BT_Muffin并點(diǎn)擊New Service驹碍。
這樣就會(huì)新建一個(gè)服務(wù)并自動(dòng)打開壁涎,我們回到Content Browser將其重命名為BTService_SetRandomLocation。
服務(wù)應(yīng)當(dāng)且僅當(dāng)在角色準(zhǔn)備移動(dòng)時(shí)才執(zhí)行志秃,因此我們要將它附著在MoveTo節(jié)點(diǎn)上怔球。
打開BT_Muffin,右鍵點(diǎn)擊MoveTo節(jié)點(diǎn)浮还,從彈出菜單選擇Add Service\BTService Set Random Location庞溜。
現(xiàn)在,當(dāng)MoveTo激活執(zhí)行時(shí)碑定,BTService_SetRandomLocation也會(huì)跟著激活執(zhí)行流码。
接著,我們需要隨機(jī)生成目標(biāo)點(diǎn)位置延刘。
生成隨機(jī)位置
打開BTService_SetRandomLocation漫试。
為了監(jiān)聽獲知服務(wù)何時(shí)觸發(fā)執(zhí)行,我們創(chuàng)建Event Receive Activation AI節(jié)點(diǎn)碘赖,這個(gè)節(jié)點(diǎn)會(huì)在服務(wù)父類(所附著的節(jié)點(diǎn))激活時(shí)觸發(fā)執(zhí)行驾荣。
注意:另一個(gè)事件Event Receive Activation也有著相同的觸發(fā)時(shí)機(jī),兩者區(qū)別在于Event Receive Activation AI事件額外提供了Controlled Pawn參數(shù)普泡。
為了生成隨機(jī)位置播掷,添加如下高亮節(jié)點(diǎn),確保將Radius設(shè)置為500撼班。
這樣就能返回得到該角色500單位半徑內(nèi)的一個(gè)隨機(jī)可達(dá)目標(biāo)點(diǎn)歧匈。
注意:GetRandomPointInNavigableRadius節(jié)點(diǎn)使用了導(dǎo)航數(shù)據(jù)(稱之為NavMesh)來判斷一個(gè)點(diǎn)是否可達(dá)。在本例中砰嘁,我已提前創(chuàng)建好了NavMesh件炉。你可以通過在Viewport選中Show\Navigation觀察NavMesh。
如果你想創(chuàng)建自己的NavMesh矮湘,請創(chuàng)建Nav Mesh Bounds Volume斟冕,縮放其大小為理想可達(dá)區(qū)域。
接下來缅阳,我們需要將位置數(shù)據(jù)存儲(chǔ)到黑板里磕蛇。有兩種方式指定要存放的鍵值:
- 我們可以使用Make Literal Name節(jié)點(diǎn)指定鍵值名字
- 我們可以將變量暴露給行為樹,這樣就能在行為樹里通過下拉列表選中變量
這里我們使用第二種方法。創(chuàng)建類型為Blackboard Key Selector的變量秀撇。將其命名為BlackboardKey并啟用Instance Editable伏伯,這樣行為樹里的服務(wù)就會(huì)出現(xiàn)對(duì)應(yīng)變量。
隨后捌袜,創(chuàng)建如下高亮節(jié)點(diǎn):
小結(jié):
- Event Receive Activation AI節(jié)點(diǎn)會(huì)在其父類(本例中的MoveTo節(jié)點(diǎn))激活時(shí)執(zhí)行
- GetRandomPointInNavigableRadius節(jié)點(diǎn)返回角色500單位半徑內(nèi)的一個(gè)隨機(jī)可達(dá)目標(biāo)點(diǎn)
- Set Blackboard Value as Vector節(jié)點(diǎn)將一個(gè)黑板鍵值(BlackboardKey)數(shù)值設(shè)為隨機(jī)位置點(diǎn)
點(diǎn)擊Compile并關(guān)閉BTService_SetRandomLocation。
接著炸枣,我們需要讓行為樹來使用這個(gè)黑板值虏等。
使用黑板
打開BT_Muffin并確保沒有選中任何東西。在Details面板的Behavior Tree設(shè)置處适肠,將Blackboard Asset設(shè)為BB_Muffin霍衫。
然后MoveTo和BTService_SetRandomLocation就會(huì)自動(dòng)使用黑板的第一個(gè)鍵值,在本例中侯养,就是TargetLocation敦跌。
最后座每,我們需要讓AI控制器來運(yùn)行行為樹葵诈。
運(yùn)行行為樹
打開AIC_Muffin并連接Run Behavior Tree節(jié)點(diǎn)與Event BeginPlay節(jié)點(diǎn),將BTAsset設(shè)為BT_Muffin齐板。
這樣當(dāng)AIC_Controller生成時(shí)就會(huì)執(zhí)行BT_Muffin辩稽。
點(diǎn)擊Compile并返回主編輯器惧笛,按下Play運(yùn)行游戲,生成一些蘑菇小人逞泄,觀察它們四處走動(dòng)吧患整。
雖然設(shè)置很繁瑣,我們還是搞定了喷众!接著各谚,我們要進(jìn)一步設(shè)置AI控制器,讓它可以在一定范圍內(nèi)感知敵人所在到千。要實(shí)現(xiàn)這點(diǎn)昌渤,就要使用AI感知(AI Perception)。
設(shè)置AI感知
AI感知是一個(gè)可以添加給Actor的組件憔四,通過它愈涩,我們可以給AI添加感官能力(如視覺和聽覺)。
打開AIC_Muffin并添加AIPerception加矛。
接著履婉,我們要添加一個(gè)感官,由于我們想要蘑菇小人能夠感知到其他小人靠近斟览,我們給它加上視覺感官毁腿。
選中AIPerception并在Details面板的AI Perception設(shè)置處,給Senses Config添加新元素。
將元素0設(shè)置為AI Sight config并展開它已烤。
對(duì)于視覺有3個(gè)主要設(shè)置:
- Sight Radius:蘑菇小人的最遠(yuǎn)視覺范圍鸠窗,將其設(shè)置為3000。
- Lose Sight Radius:如果蘑菇小人已經(jīng)看到了敵人胯究,那敵人要逃離小人視野的距離稍计,將其設(shè)置為3500。
- Peripheral Vision Half Angle Degrees:決定蘑菇小人視野的角度裕循,將其設(shè)置為45臣嚣,蘑菇小人就會(huì)有90度的范圍視角。
默認(rèn)情況下剥哑,AI感知只檢測敵人(被指定為不同隊(duì)伍(team)的Actor)硅则。然而,Actor默認(rèn)是沒有設(shè)置隊(duì)伍的株婴,如果Actor沒有隊(duì)伍怎虫,AI感知就會(huì)將其認(rèn)為中立(neutral)角色。
截至目前困介,還沒有方法能通過藍(lán)圖設(shè)置Actor的隊(duì)伍大审,退而求其次,我們展開Detection by Affiliation設(shè)置座哩,啟用Detect Neutrals饥努。
點(diǎn)擊Compile并回到主編輯器。按下Play運(yùn)行游戲來生成蘑菇八回。按下 ‘ 鍵可以顯示AI調(diào)試信息酷愧,按下小鍵盤的數(shù)字鍵4可以可視化AI感知組件。當(dāng)蘑菇小人進(jìn)入視野時(shí)缠诅,就會(huì)顯示綠色球體溶浴。
接著,我們要讓蘑菇小人往敵人的方向走去管引。要實(shí)現(xiàn)這點(diǎn)士败,行為樹就要了解敵人的信息,我們通過在黑板存儲(chǔ)敵人的引用來完成這件事褥伴。
創(chuàng)建敵人鍵值
打開BB_Muffin并添加類型為Object的鍵值谅将,將其命名為Enemy。
現(xiàn)在重慢,我們還不能在MoveTo節(jié)點(diǎn)使用Enemy饥臂,因?yàn)槠滏I值類型為Object,但MoveTo只接受Vector或Actor類型的鍵值似踱。
為了解決這點(diǎn)隅熙,我們選中Enemy并展開Key Type稽煤,將Base Class設(shè)置為Actor。這樣行為樹就能將Enemy識(shí)別為Actor了囚戚。
關(guān)閉BB_Muffin酵熙,現(xiàn)在,我們要?jiǎng)?chuàng)建一個(gè)行為讓AI向敵人走去驰坊。
朝敵人移動(dòng)
打開BT_Muffin并斷開Sequence和Root連接匾二。我們可以通過按住Alt鍵點(diǎn)擊連線來做到,并將移動(dòng)子樹移到一邊拳芙。
接著察藐,創(chuàng)建如下高亮節(jié)點(diǎn),并將Blackboard Key設(shè)置為Enemy:
這樣角色就會(huì)朝Enemy走去态鳖。有時(shí)候,角色不會(huì)剛好面對(duì)著它的目標(biāo)恶导,所以我們還需要用上Rotate to face BB entry節(jié)點(diǎn)浆竭。
現(xiàn)在,我們需要在AI感知檢測到其他蘑菇時(shí)惨寿,將其設(shè)置為Enemy的值邦泄。
設(shè)置敵人鍵值
打開AIC_Muffin并選中AIPerception組件,添加Perception Updated事件裂垦。
只要感官發(fā)生更新顺囊,這個(gè)事件就會(huì)觸發(fā)執(zhí)行。在本例中蕉拢,當(dāng)AI獲得或丟失了某物體的視野特碳,這個(gè)事件就會(huì)執(zhí)行,并提供了其當(dāng)前所能感知到的Actor列表晕换。
添加如下高亮節(jié)點(diǎn)午乓,并確保將Make Literal Name節(jié)點(diǎn)設(shè)置為Enemy。
這樣就可以判斷AI目前有沒有敵人對(duì)象闸准,如果沒有益愈,我們就要給它設(shè)置一個(gè)敵人,因此添加如下節(jié)點(diǎn):
小結(jié):
- IsValid節(jié)點(diǎn)負(fù)責(zé)判斷Enemy鍵值是否有值
- 如果還沒設(shè)置夷家,遍歷當(dāng)前所有檢測到的Actor
- Cast To BP_Muffin節(jié)點(diǎn)負(fù)責(zé)檢查Actor是否為蘑菇
- 如果是蘑菇蒸其,進(jìn)一步判斷是否已死亡
- 如果IsDead返回false,將蘑菇設(shè)置為新敵人库快,并退出循環(huán)
點(diǎn)擊Compile并關(guān)閉AIC_Muffin摸袁,按下Play運(yùn)行游戲并生成兩個(gè)蘑菇小人,其中一個(gè)生成暴露在另一個(gè)面前义屏,后者就會(huì)自動(dòng)向前者走過去但惶。
接著耳鸯,你要?jiǎng)?chuàng)建一個(gè)自定義任務(wù),讓蘑菇小人可以表演攻擊行為膀曾。
創(chuàng)建攻擊任務(wù)
我們可以直接在Content Browser創(chuàng)建任務(wù)县爬,而無須通過行為樹編輯器。創(chuàng)建新的Blueprint Class類添谊,并將BTTask_BlueprintBase作為其父類财喳。
將新建類命名為BTTask_Attack并打開,添加Event Receive Execute AI節(jié)點(diǎn)斩狱,這個(gè)節(jié)點(diǎn)會(huì)在行為樹激活BTTask_Attack時(shí)觸發(fā)執(zhí)行耳高。
首先,你需要讓蘑菇執(zhí)行攻擊行為所踊。BP_Muffin包含一個(gè)IsAttacking變量泌枪,當(dāng)變量設(shè)置為true時(shí),蘑菇會(huì)執(zhí)行一次攻擊秕岛,因此我們添加如下高亮節(jié)點(diǎn):
如果這個(gè)任務(wù)節(jié)點(diǎn)在這里就結(jié)束了碌燕,那行為樹執(zhí)行就會(huì)卡在這個(gè)節(jié)點(diǎn)上,因?yàn)樾袨闃洳⒉恢涝摴?jié)點(diǎn)已執(zhí)行完畢了继薛,所以我們要在節(jié)點(diǎn)鏈末端添加Finish Execute節(jié)點(diǎn)修壕。
接著,啟用Success遏考,由于我們用的是Sequence慈鸠,這樣就能讓BTTask_Attack的后續(xù)節(jié)點(diǎn)得以執(zhí)行。
現(xiàn)在圖表看起來應(yīng)該是這樣的:
小結(jié):
- 當(dāng)行為樹激活BTTask_Attack節(jié)點(diǎn)時(shí)灌具,Event Receive Execute AI節(jié)點(diǎn)就會(huì)一同觸發(fā)執(zhí)行青团。
- Cast To BP_Muffin節(jié)點(diǎn)會(huì)檢查Controlled Pawn是否為BP_Muffin類型
- 如果是,則設(shè)置IsAttacking變量為true
- 通過Finish Execute節(jié)點(diǎn)退出當(dāng)前節(jié)點(diǎn)咖楣,讓行為樹繼續(xù)往下執(zhí)行
點(diǎn)擊Compile并關(guān)閉BTTask_Attack壶冒。
現(xiàn)在,我們需要將BTTask_Attack節(jié)點(diǎn)添加到行為樹中截歉。
行為樹添加攻擊行為
打開BT_Muffin胖腾,隨后,將BTTask_Attack節(jié)點(diǎn)添加到Sequence節(jié)點(diǎn)后面瘪松。
接著咸作,將Wait節(jié)點(diǎn)添加到Sequence節(jié)點(diǎn)后面,并將Wait Time設(shè)置為2宵睦。確保蘑菇小人不會(huì)攻擊個(gè)不停记罚。
回到主編輯器點(diǎn)擊Play運(yùn)行游戲,像上次一樣生成兩個(gè)蘑菇小人壳嚎。蘑菇小人會(huì)朝著敵人走去桐智。隨后末早,它會(huì)嘗試攻擊,然后休息兩秒说庭。當(dāng)它發(fā)現(xiàn)另一個(gè)敵人時(shí)然磷,又會(huì)重復(fù)以上行為。
在最后一部分刊驴,我們要將攻擊和移動(dòng)兩顆子樹合并在一起姿搜。
合并子樹
為了合并子樹,我們要用上Selector組合節(jié)點(diǎn)捆憎。類似于Sequence節(jié)點(diǎn)舅柜,它也是按從左向右的順序執(zhí)行的。然而躲惰,Selector節(jié)點(diǎn)會(huì)在子節(jié)點(diǎn)返回成功而非失敗時(shí)停止執(zhí)行致份。利用這個(gè)特性,就可以確保行為樹每次只執(zhí)行一顆子樹础拨。
打開BT_Muffin并在Root節(jié)點(diǎn)下創(chuàng)建Selector節(jié)點(diǎn)氮块。隨后,如下圖連接兩個(gè)子樹:
這樣同一時(shí)間只有一顆子樹會(huì)得到執(zhí)行太伊,下面是每顆子樹的執(zhí)行情況:
攻擊: Selector節(jié)點(diǎn)會(huì)首先運(yùn)行第一顆子樹雇锡,如果所有任務(wù)都成功了逛钻,Sequence節(jié)點(diǎn)也會(huì)返回執(zhí)行成功僚焦。Selector節(jié)點(diǎn)得知執(zhí)行成功,就會(huì)停止執(zhí)行后面的節(jié)點(diǎn)曙痘,這樣就不會(huì)再執(zhí)行移動(dòng)節(jié)點(diǎn)芳悲。
移動(dòng): Selector節(jié)點(diǎn)會(huì)嘗試運(yùn)行前面的攻擊子樹,如果Enemy還沒有值边坤,MoveTo節(jié)點(diǎn)就會(huì)執(zhí)行失敗名扛,Sequence節(jié)點(diǎn)也就同樣失敗。由于第一個(gè)子樹失敗了茧痒,Selector節(jié)點(diǎn)就會(huì)執(zhí)行后續(xù)這顆移動(dòng)子樹肮韧。
回到主編輯器,按下Play運(yùn)行游戲旺订,生成一些蘑菇小人試試看吧弄企!
“等等,為什么圖中這個(gè)蘑菇小人沒有馬上攻擊另一只呢区拳?”
在傳統(tǒng)的行為樹設(shè)計(jì)里拘领,行為樹每幀都會(huì)從根節(jié)點(diǎn)開始執(zhí)行,意味著每幀更新樱调,它都會(huì)嘗試執(zhí)行第一顆攻擊子樹约素,然后再執(zhí)行第二顆移動(dòng)子樹届良,這也意味著當(dāng)Enemy值發(fā)生變化時(shí),行為樹就會(huì)馬上切換執(zhí)行另一顆子樹圣猎。
然而士葫,Unreal的行為樹并不是這樣設(shè)計(jì)執(zhí)行的。在Unreal里样漆,行為樹會(huì)繼續(xù)執(zhí)行上一幀選中的那顆子樹为障。圖中由于AI感知沒有馬上感知到另一只蘑菇小人的存在,行為樹開始執(zhí)行移動(dòng)子樹放祟,于是行為樹就只能乖乖等待移動(dòng)子樹執(zhí)行完畢鳍怨,才能重新評(píng)估確定執(zhí)行攻擊子樹。
為了解決這個(gè)問題跪妥,我們需要用上最后一種類型節(jié)點(diǎn):裝飾(decorators)節(jié)點(diǎn)鞋喇。
創(chuàng)建裝飾節(jié)點(diǎn)
類似于服務(wù)節(jié)點(diǎn),裝飾節(jié)點(diǎn)也依附于任務(wù)或組合節(jié)點(diǎn)眉撵。通常而言侦香,裝飾節(jié)點(diǎn)用于做前置檢查。如果檢查結(jié)果為true纽疟,裝飾節(jié)點(diǎn)就返回true罐韩,反之亦然。通過裝飾節(jié)點(diǎn)污朽,就能控制其依附節(jié)點(diǎn)是否能夠執(zhí)行散吵。
裝飾節(jié)點(diǎn)也有能力中止子樹的運(yùn)行,這意味著我們能實(shí)現(xiàn)一旦Enemy有設(shè)值蟆肆,就立即中止移動(dòng)子樹矾睦。這樣蘑菇小人就能在發(fā)現(xiàn)敵人的第一時(shí)間攻擊敵人。
要實(shí)現(xiàn)中止功能炎功,我們可以使用Blackboard裝飾節(jié)點(diǎn)枚冗,這個(gè)節(jié)點(diǎn)只是簡單地檢查某個(gè)黑板鍵值是否有值。打開BT_Muffin蛇损,并在攻擊子樹的Sequence節(jié)點(diǎn)點(diǎn)擊右鍵赁温,從彈出菜單選中Add Decorator\Blackboard,這樣Sequence節(jié)點(diǎn)就會(huì)添加上Blackboard節(jié)點(diǎn)淤齐。
接著股囊,選中Blackboard裝飾節(jié)點(diǎn),并在Details面板將Blackboard Key設(shè)為Enemy床玻。
這樣可以判斷Enemy是否有值毁涉,如果沒有值,節(jié)點(diǎn)返回失敗锈死,從而導(dǎo)致Sequence失敗贫堰,從而讓移動(dòng)子樹得到執(zhí)行穆壕。
為了中止移動(dòng)子樹,我們需要用上Observer Aborts設(shè)置其屏。
使用Observer Aborts
Observer Aborts能夠?qū)崿F(xiàn)所選中的黑板鍵值發(fā)生變化時(shí)喇勋,中止執(zhí)行子樹,這里分為兩種類型的中止:
- Self: 該設(shè)置允許當(dāng)Enemy值失效時(shí)偎行,立即中止運(yùn)行攻擊子樹川背,這種情況發(fā)生在攻擊子樹還未運(yùn)行完畢,而Enemy又死亡的時(shí)候蛤袒。
- Lower Priority:該設(shè)置允許當(dāng)Enemy有值時(shí)熄云,中止運(yùn)行較低優(yōu)先度的子樹。由于移動(dòng)子樹放在攻擊子樹后面妙真,它就是較低優(yōu)先度子樹缴允。
我們將Observer Aborts設(shè)為Both,同時(shí)啟用兩種類型的中止珍德。
現(xiàn)在练般,當(dāng)AI已經(jīng)沒有敵人目標(biāo)時(shí),可以馬上從攻擊子樹切換運(yùn)行移動(dòng)子樹锈候。同樣的薄料,當(dāng)AI檢測到敵人目標(biāo)時(shí),又能從移動(dòng)子樹切換運(yùn)行攻擊子樹泵琳。
以下是完整的行為樹圖表:
攻擊子樹小結(jié):
- 當(dāng)Enemy有值摄职,Selector開始運(yùn)行攻擊子樹
- 一旦運(yùn)行子樹,角色開始朝敵人走去
- 隨后虑稼,進(jìn)行攻擊
- 最后琳钉,角色原地停留2秒
移動(dòng)子樹小結(jié):
- 當(dāng)Enemy沒有值势木,攻擊子樹運(yùn)行失敗時(shí)蛛倦,Selector繼續(xù)運(yùn)行移動(dòng)子樹
- BTService_SetRandomLocation生成一個(gè)隨機(jī)位置
- 角色朝指定位置移動(dòng)
- 隨后,角色原地停留5秒
關(guān)閉BT_Muffin并按下Play運(yùn)行游戲啦桌,生成一些蘑菇小人進(jìn)行一場你死我活的決斗吧溯壶!
后續(xù)學(xué)習(xí)
你可以在這里下載完整項(xiàng)目。
如你所見甫男,制作簡單AI還算一件不難的事且改。如果你想創(chuàng)建一個(gè)更加高級(jí)的AI,請查閱場景查詢系統(tǒng)板驳,這個(gè)系統(tǒng)允許AI收集場景數(shù)據(jù)并作出相應(yīng)的反饋又跛。
如果你還想繼續(xù)學(xué)習(xí)引擎其他內(nèi)容,點(diǎn)擊下篇教程若治,將教你如何制作一個(gè)簡單的第一人稱射擊游戲慨蓝。