【摸魚向】UE4的AI模塊探索手記(1)

前言

以前實現了自主創做的角色導入進UE4併成功控制其進行一系列動做,但目前的樣子距離基本的遊戲架構還差了一個很大的模塊:NPC,而這部分是由電腦來進行自動控制,因此,我有一句話不知當講不當講(對,我又不知足了( •̀ ω •́ )✧)。由此,我又一次打開了官方文檔,開始對UE4中比較難啃的AI模塊進行探索。(前方少圖,請放心加載(笑))編程

正文

一.構成

先說一下UE4中AI的構成,通常若是是對玩家有威脅的敵人角色或者是跟隨玩家的npc角色,它們的配置通常有:1.行爲樹;2.黑板;3.AI控制器;4.AI角色;5.相關服務;6.相關修飾器;7.相關任務。本次以相似於《合金裝備》裏敵兵的AI構建爲例,對各個配置進行說明與我的看法。數據結構

1.行爲樹

UE4的AI角色核心,屬於決策層配置,大體樣貌以下:

若是你有一些程序設計基礎,那麼大體經過名字就能判斷行爲樹是由相似於if—else一類的決策組成的AI行動方案。而且行爲樹是一種能夠進行相似深度優先遍歷操做的數據結構,即好比在某個子樹的行爲已經運行完成後,狀態改變,則此時根據改變的條件選擇須要遍歷的子樹接着進行遍歷與運行操做。而組成行爲樹的節點可並非相似於普通樹狀結構中單一僅含有權重的「小圓圈」,行爲樹通常由如下幾種節點組成:Root,Composites和Tasks。接下來分別描述一下三種節點:架構

a.Root節點

又名根節點,是整個行爲樹的核心與基礎,一但當Agent在場景中的實例化被調用時,那麼,Root就是行爲樹的調用入口,今後處開始AI行爲邏輯。因爲其固定的性質,因此Root節點不可進行編程。dom

b.Composites節點

直譯過來是「複合體」,根據其節點的做用,又分爲Sequence,Selector和Simple Parallel(此節點暫不作敘述),其中,Sequence(隊列)是爲了讓其下的子節點或子樹按照順序標號的順序進行執行的節點,而Selector則是行爲樹中最重要的「選擇單元」,經過某些「特殊」的「玩意兒」實現對於狀態(通常是用整型,浮點,或枚舉表示狀態)的判斷,從而選擇相關的子樹。與Root一樣含有固定的性質,因此不可編程。學習

c.Tasks節點

又名任務節點,即上述的「相關任務」,是相同的東西,這裏具體記載着Agent的行爲,當遍歷執行到這裏時,Agent便會作出行動,好比跑,跳等。因爲AI的行爲依據具體狀況決定,因此在引擎默認建立的幾個Tasks節點以外,開發者還能夠編寫新的Tasks節點,即Tasks節點是可編程的(行爲樹插圖中紫色的部分)。人工智能

2.黑板

黑板是用來存儲一系列Agent狀態變量的一種結構體,好比此時Agent發現了玩家而且向玩家跑過來,因此它此時的狀態至少就應該有這麼幾個:玩家此時的位置,Agent的移動類型(Idle或者Running)以及玩家最後一次出現的位置,這些東西都要用變量存儲起來。然而各個任務節點與一系列的服務,修飾器之間是毫無聯繫且相互獨立的,因此他們之間並不能直接修改對方的數據,這時候就要經過黑板裏面的數據做爲接口實現整個系統之間的通訊。而且實際上這些數據並無保存在黑板裏面,黑板只是提供了一種定義方式,行爲樹會自行建立一個黑板,將全部數據存儲在那裏面,只是行爲樹建立的黑板會聽從原黑板的數據格式罷了。真不知道Epic官方是怎麼起名的,叫「記憶體」或「數據塢」這種高大上狂拽酷炫屌炸天的名字它不香麼?(或許Epic有這種想法的合理性吧,咱對人工智能的基礎理論知之甚少,若是有哪位大佬知道,歡迎補充)設計

3.AI控制器與AI角色

這即是AI在遊戲場景中的實例化,也是最終展示給玩家的樣貌。由控制器控制角色進行相應的動做,由行爲樹做爲多觸手章魚玩家來操做多個控制器從而控制多個角色。3d

4.服務

開發人員以及玩家們都但願在作出一系列的舉止後(好比製造噪聲,向敵人扔個小黃書等),Agent能夠根據這種舉止作出相應行動,即遵照圖靈機的基本定義「輸入必定的數據——處理數據——輸出相應的處理結果」。試想,若是不接受玩家的輸入從而在場景內亂跑,那豈不就與喵星人的掃地座駕以及辣個女人同樣麼?
人工智障
因此,服務就是來幹這事的。一般,服務通常用來接收此時場景內的狀況輸入,好比玩家進入視錐,而且玩家並無躲在牆體後面,這時服務就會獲取這些信息的輸入,而且經過邏輯處理從而將黑板中的狀態數據進行改變並更新。固然,因爲一個Agent的行爲在不一樣的遊戲類型中(甚至不一樣關卡中)會接受多種不一樣的輸入,而且黑板上的數據也並非必定相同的,因此,服務完徹底全是可編程的(行爲樹插圖中青色的部分)。blog

5.修飾器

好的,這時候咱們已經獲取了環境的信息並改變了Agent的狀態,若是咱們但願Agent根據此時的狀態作出相應的行爲,那麼就須要Selector進行選擇。然而,如何讓Selector進行選擇,總不能隨機選一個?若是是這樣,那麼Selector以及Agent的狀態便毫無心義因此,這即是「那個玩意兒」——修飾器的做用:做爲執行其負責的子樹部分的斷定條件,也就是if—else結構中括號裏填寫的那個條件,即定義的條件知足後再運行相應子樹,若不知足則退回上一節點。通常都使用基於參考黑板數據的修飾器。固然,斷定條件也有可能與關卡狀態,玩家狀態甚至是你的電腦狀態等黑板中並無存儲的數據相關,因此,修飾器也是可編程的。(行爲樹插圖中藍色的部分)接口

二.聯繫

接下來以我最喜歡的PS2遊戲之一《合金裝備2:自由之子》(我絕對不是由於能夠在廁所裏看海報而喜歡的)其中一個場景進行說明(請結合行爲樹插圖食用更佳),具體場景以下所示:

此時玩家操縱的蛇叔處在A點,他要前往的B點(rush B)附近有敵兵看守,此敵兵假如說就是咱們描寫的Agent,而且在相應的黑板中建立了這樣幾個變量State(Agent的狀態,枚舉類型:Idle,Combat,Searching),Player(準確的說是Agent前往的地點),PlayerMarker(玩家在Agent可視範圍消失後最後一次出現的位置);這時,Agent在場景中實例化,因此,引擎會調用Agent所使用的行爲樹的Root節點,此時行爲樹開始工做。首先這時Agent面向牆壁,而在行爲樹中的EnemyTrial_SearchVision服務爲Agent正方向創造了一個110度(角度)的視錐,此時玩家並無在視錐範圍內,因此EnemyTrial_SearchVision服務將此時Agent的State設置爲Idle,目標前往地點與玩家最後一次的位置設置爲空。接下來進行選擇,Selector會經過本身全部分支中的修飾器進行選擇,既然此時狀態爲Idle,那麼State equal Idle修飾器符合條件,因此接下來執行此修飾器下的子樹,而後此時Agent的行爲由EnemyTrial_SetWalkSpeed(設置此時Agent的行走速度:巡邏速度)以及EnemyTrial_MoveToRandomPoint(讓Agent隨機移動到某點)定義並控制Agent執行。在執行的過程當中,服務以及修飾器也沒閒着,一旦此時Agent隨機移動的點在A點附近,Agent須要轉身,而此時玩家操做的蛇叔正好探頭與Agent對上了眼(進入視錐)。那麼,服務會當即改變此時Agent的State爲Combat,並且將Player與PlayerMarker設置爲此時玩家的位置,修飾器監視到State改變,因此會當即中斷自身的行爲,並將進度當即返還到Selector,而後由Selector分配給State equal Combat,接着執行Combat對應的Agent行爲。可是,若是此時蛇叔打開了光學迷彩(這是不可能的,由於從橋上跳下來時已經摔壞了),在視錐中消失,這時服務將Player設置爲空,並會檢索黑板中的PlayerMarker,若是PlayerMarker非空,則Agent的Selector將進度交給State equal Searching,總不能Agent看不到敵人就放棄搜索吧(山貓:你已經被開除了),若是PlayerMarker爲空,那麼Agent的Selector會將進度交給State equal Idle(通常這種狀況不可能,除非玩家開了修改器)。接着,當Agent到達PlayerMarker後,在其搜索的時間內若是沒有在視錐內發現玩家,那麼EnemyTrial_DestroyMarker任務便會清空Player與PlayerMarker,而且將State設置爲Idle,這時修飾器監測到了State的改變,因此此時又會將進度返還給Selector,再由Selector將進度交給State equal Idle,實行Agent基礎的巡邏狀態。

結語

又開了一個坑……我也想好好作個遊戲啊%&*#@!¥%%#(因言語過激而被踢出直播間),可是基礎不足,身邊也沒有學習美工與音效的小夥伴,只能本身慢慢摸索了,C++也在補STL方面的基礎,不過這卻是充足了網課後的課餘時間(笑)。若是個人這篇文章裏面的相關名詞與解釋有不正確或是容易引起歧義的地方,歡迎在評論區指出。並且若是你對於其中的一些解釋還有不明白的地方,也歡迎騷擾。固然,老規矩,若是你認爲這篇文章會對更多的人有幫助,歡迎轉載,只不過請註明轉載出處便可,以上。どうもありがとうございました!(都莫,阿里嘎多靠薩依瑪希大!)

相關文章
相關標籤/搜索