首先做個小小的聲明把,由於俺之前也沒接觸過AI ,所以有一些專業的詞匯可能翻譯存在各種問題,如果你發現的話,還是希望能夠提出來哦,我們一起進步。
記住配合視頻食用更佳哦~
視頻連接:http://www.unrealedu.org/course/15/learn#lesson/79
此外,我也在翻譯官方那本C++的教程,已經讀完,想着還是用視頻的方式來准備,大家如果有什么意見希望可以提出來。好了廢話不多說,開譯!
第一篇:簡單了解AI並創建NavMesh
嗨,大家好,我是PeterNew,謝謝大家收看我的AI NewMesh(自動尋路)演示教程。接下來的五段視頻主要會接觸到UE4的nevMesh自動尋路,當然也有行為樹(Behavior Tree),那將會成為處理AI最有效的辦法。好的,接下來呢,我們將會創建一個NevMesh,創建一個AI角色,創建一個控制器,並且創建WayPoint(導航點),數據資源(data assets),bot狀態枚舉,創建用來控制bots的行為樹,我們接下來將會針對行為樹創建一些任務,裝飾器和服務? 接下來我將會詳細的講述這些組件功能。那現在我們就開始吧。
首先我要給你們展示一下到目前為止,我做出來的功能,這也是你們今天要做的。正如你所看到的,現在有一些我添加的任務他決定了AI可以接下來做啥,有很多不同的導航點,1,2,3...on,這個家伙開始向我攻擊,哦,他讓我掉了下來,你可以發現,這家伙他可以正常工作,但總是給我惹一些麻煩。好的,這里有很多我定義的動作,你會發現AI角色慢慢的從導航點1一直移動到6,好吧,他又一次看到了我。沒有什么可以阻擋他,走到設置的導航點那里。好吧,那我們就正式開始吧。好的,正如你所看到的,我剛剛僅僅把之前的關卡在這里復制了一份,當然,我忘了一件事,我的名字。我從不開玩笑o(╯□╰)o。
好的,接下來我們添加自動尋路的區域邊界(NavMeshBoundsVolume),(這幾個點,移動一下,這幾個點,移動一下o(╯□╰)o,接下來就是調整邊界的大小)。注意,這個自動尋路的區域一定要包裹住整個你想要生成自動尋路能夠到達的所有地方,好了,就像你看到的,它已經包圍住了所有的東西。接下來要創建自動尋路Buid NavMesh,好了,我們已經創建好了NavMesh,如果想要編輯你的navMesh。
你可以搜索一下RecastNav(編輯NavMesh),你會在這里發現一些設置,有很多選擇可以控制你的NavMesh究竟如何工作,這里呢,我就使用默認的了,要想創建你的AIbot,我們需要使用一個經常使用的角色,添加一些資源,做一點簡單的修改。我們經常會看到這個藍色的男人,但這里我將會使用一個不同的角色,如果你對這個角色很熟悉的話,沒錯,他就包含在虛幻四的那個Content的項目中,我給他添加了一把槍,添加了一些例子效果(比如...和拖尾)。
然后,你創建兩個事件,一個用來通知acotr發現了敵人,一個用來通知actor敵人已經消失,好,首先創建第一個事件:發現敵人(EnemyFound),第二個敵人消失(EnemyLost),作為演示,這就是我主要使用的actor,好吧,發現敵人就開始攻擊,敵人消失就停止攻擊,把兩個事件拖放到場景中,創建事件,我簡單給你演示一下怎么改變actor 的動畫,首先獲得Mesh->播放動畫->選擇動畫資源。接下來說第二種,當發現敵人的時候,它開始播放,當敵人消失的時候,你將會充值動畫,讓他還原到默認狀態。GetMesh->SetAnimationMode,然后就可以使用動畫藍圖了,這樣就可以重置動畫到任何你已經存好的狀態了。好了保存,編譯。
接下來,我們需要創建AI 控制器,創建藍圖類,父類選擇AIController,命名為botAI。然后你會發現這里有一些不用的組件。在圖表中,輸入事件BeginPlay-》RunBehaviorTree(運行行為樹)。現在我們還沒有行為樹,保存編譯一下,接下來我們要創建一個枚舉,用來定義狀態和轉換,創建枚舉,(譯者注:注意,我這里最新版的UE4枚舉是在“藍圖”里面)命名為botState,添加一個Patrol,Search,和Attack。接下來我們要創建的是數據資源(deadAssets),數據資源類別選擇Blackboard,取名為botData,在這里我們創建一些函數可以引用到的信息。接下來我們要創建的第一個都給就是目標點,這將告訴我們的角色它要去的下一個地方,KeyType為BlackBoardKyeType_Vector。接下來創建AI的狀態,KeyType為枚舉Enum,選中我們剛剛創建好的botState枚舉。接下來創建敵人,取名為EnemyActor,KeyType為Object。接下來我們創建路線(Route),KeyType為int。這樣就都創建完畢了。
接下來我們就要創建AIbot 了,在這之前,這個選項還不能找到,我們需要設置一下。點擊編輯--編輯器偏好設置--實驗性功能--勾選BehaviorTreeEditor(譯者注:我用的4.7版本的UE4已經沒有這一項了)。好了,接下來就創建一個BehaviorTree(其他--行為樹),取名為botAITree,打開它。你要注意的第一項內容是blackboard,這里我們要選擇botData,這將會告訴bot在運行的access thing and reference thing整個過程里要做什么(?)。接下來要創建的是AI way point(航路點),新建一個藍圖類,父類為TargetPoint,取名為botWayPoint,打開它,添加一個變量,取名為Position,int類型,讓他變成可以被編輯的(共有的),保存編譯。接下來就要定義一些導航點了,如果你還記得之前的演示的話,這里有一個,那里有一個....1,2,3,4,5,6。觀察我的工程你將會發現有6個標記,從1-6 Position的值由0變到5。
好的,接下來我們要創建的是任務task,第一個任務是角色走的由慢變成快,回到botCharacter藍圖,創建一個Tick事件,GetCharacterMoment->SetMaxWalkSpeed,創建兩個變量,一個是SpeedRate和SpeedVariable,都是int,編譯。SpeedVariable的默認值為150,speedRate的默認值為1。SpeedVariable * SpeedRate 結果作為輸入連接到MaxWalkSpeed。把這個拖放下來,連起來,這就是我們要的。這里的所有東西就是我的射擊邏輯了。保存編譯。
接下來我想做的是改變行走的速度,創建一個藍圖類,父類為BTTask_BlueprintBase,取名為BTT_BotWalkSpeed,到目前為止,我們還沒有創建一個行為樹的任務,你需要右鍵添加一個叫做EventReceiveExecute的事件節點,給他添加一個注釋:BeginExecute,下一個創建FinishExcute(完成執行),建立這兩個節點的原因是為了讓行為樹之間溝通,一開始,你通知這個BeginExecute,接下來當你完成以后,你使用finishe這個節點告訴行為樹,完成了。整個過程其實很簡單。acotor會被行為樹控制立刻執行,如視頻當中連接,把otherActor轉換為botAI->GetControlledPawn->CastToBotCharactor,這樣的話,我們就可以訪問WalkSpeed的變量了,>SetSpeedRate,把這個節點連接到FinishExecute上,我們給這一段添加一個注釋:改變BOt的行走速度。我們需要另外一個變量以便可以在行為樹里面更改行走的速度,新建變量WalkRate,類型為float,並且設置為可以被編輯的(公有變量),把它獲得並連接到這里,編譯,保存,默認值設置為1。保存一下。既然現在你可以編輯你的第一個行為樹的任務,接下來,我們將會在下一段視頻中介紹怎么讓bot四處巡邏起來~
第二篇:了解AI Navigation
現在是教程的第2/5部分,我們將會給敵人創建行為樹任務,和導航bot 完成 do the rounts(路),我們將可以導航bot走向敵人,好了,,創建藍圖類,父類為BTTask_BlueprintBase,取名為BTT_botNextRoute,打開它,在這個任務里我們需要添加兩個BlackboardKeySelector變量,首先創建TargetPoint,類型為BlackboardKeySelector,創建另一個,Route。接下來我們要創建另外一個變量,maxRoutes,它定義了AI要尋找有多少條路,即使我們在這里創建了導航點,我們也有可能需要我們的AI角色控制你的任務,所有把這三個變量全部變成共有可編輯的,保存。然后,和之前一樣,我們要添加兩個事件:事件ReceiveExecute(4.7中文版本),和FinishExecute並給他們添加注釋:開始執行、結束執行。接下來首先獲得Route->GetBlackboardValueAsInt(以int型獲得黑板值),並且和maxRoute做比較,如果大於等於maxRoute,則把黑板值設置為0,然后獲得所有botWayPoint類的對象,然后或得到數組里面的每一個元素,使用ForEachWIthBreak節點,把complete端口,連接到finish的入口處,把finish執行事件節點稍微往后拖放一下,接下來我們把數組中的元素轉換為botWayPoint,獲得每一個的位置,復制一下左邊的節點,比較他們是否相等,接下來我們要做的是把黑板值blackboardvalue值設置成vector,所以,我們先或得到TargetPoint的變量,把它設置為vector,我們先把finish節點拖放下來,位置信息是來源於這里,所以,獲得數組中物體的位置,把他們賦值給TargetPoint,保存編譯一下。
接下來我們要回到AI行為樹,來完成下面要做的,點擊節點,就像我們圖表里面節點一樣,獲得選擇器(selector),選擇器將會調用位於他下面的所有事情,還有一個節點叫做序列(Sequence),而這個節點只在當之前的函數被成功調用后,調用下一個函數,所以這邊是按照順序來執行的,這就是sequence,而selector會調用所有的。還有一個節點叫做SimpleParallel,這個節點允許你調用一個函數,而它調用另外一個函數,所以這邊可以是BTT_WalkSpeed,而另一邊可是調用MoveTo,這兩個任務是同時調用的。而在這里,我們想做的是,創建另一個選擇器(selector),接下來調用BTT_botWalkSpeed,接下來我們還要調用BTT BotNextRoute,最后一個要調用的函數是MoveTo,這里就是這些函數了,改一下節點的名字,“ChangeWalkSpeed”,這樣就更容易被編輯,第二個節點的名字改為FindRoute,第三個MoveToRoute。第一個節點這里問可以看到之前定義的變量WalkRate行走速度,我們把它改為2,第二個節點,這邊有幾個變量,TargetPoint和Route都是共有的,首先根節點告訴你要開始行走了,接下來,這兩個值告訴你應該從哪里走到哪里,所以我們的TargetPoint變量的值為TargetPoint對象,而Route的值為Route對象,MoveToRoute這里需要一個黑板值,所以它需要做導航,所以Blackboard這里要選擇TargetPoint。
接下來我們為選擇器節點添加另外一個東西,這樣他就可以正確的選擇了,右鍵點擊,添加一個裝飾器,值為Blackboard,選擇添加的這個黑板值,把它的名字改為巡邏(patrol),它的黑板值為State,KeyQuery為isEqualTo,(查詢類型為是否等於)值為巡邏,好了,所以這一部分正常發揮作用的前提是,bot的狀態為巡邏。我們在另一邊創建另外一個選擇器,做同樣的事情,添加黑板blackboard裝飾器,改名為搜尋並且攻擊(Search & Attack ),選擇blackboard的值為state,查詢類型為大於等於,值為Search或者attack,所以只有當攻擊或者搜尋的時候,才會調用這邊。我們給他自動排列一下。search&Attack 這個裝飾器和之前的有點不同,你可以創建自己的裝飾器,裝飾器是一些加在任務上的一些條件,我們來快速瀏覽一下這些裝飾器們,這里有ForceSuccess、循環、限時、達到目標,這些裝飾器可以多個用來額外的添加到任務上,所以你可以同時限制forceSuccess或者超時等等你想要的條件。
好了,接下來我們回到內容瀏覽器。我要添加另外一個任務叫做MoveToEnemy(向敵人移動),同樣創建一個父類為BTTask_BlueprintBase的藍圖類,取名為BTT_botMoveToEnemy,我們首先創建兩個黑板類的變量,一個是路(route),一個是狀態(state),第一個取名為敵人物體(enemyActor),另外一個是State,接下來我們創建一個半徑(Radius),用來判斷到敵人的距離(?And This is simply allow you to minite delate,the subtance radios from the move to the actor),把這些變量都改成公有的。接下來創建事件ReceiveExecute節點,把actor 轉換為botAI,我們想要獲得他的狀態,以枚舉的方式獲得黑板值,然后我們想要通過boteState的狀態來做出選擇,如圖連接,把這兩個往上移動一下,把state節點往下移動一下,騰出更多的空間,我們想要或得到敵人物體(enemyActor),以object的類型獲得他的黑板值,把這個object轉換成角色Character,從search的端口連接過來,接下來我們設置ai的焦點(?),我想做另外一件事,設置物體的旋轉信息,所有我們或得到botAI被控制的pawn,設置它的旋轉信息,或得到角色的位置,然后獲得AIbot到玩家的LookAt對應角度,把角度的三個值分離,制作一個旋轉值,僅僅只改變yaw,接下來繼續獲得物體的旋轉信息,使用RInterTo節點,制作好的Rot作為目標值,得到的信息作為當前值,使用GetWorldDeltaSeconds節點,把插入速度改為6,來更新旋轉信息。
接下來控制botAI 使用MoveToActor節點,把Radios值作為AcceptanceRadios,關閉CanStrafe,把你的目的actor轉換為節點當中的目標端口值,往下走兩行,我們來設置物體的旋轉信息,從attack的輸出端口連過來,把新得到的旋轉值放到這里,這意味着當角色正在被攻擊的時候,他是可以被吸引的(engaged)。
最后我們要做的是,添加完成執行節點,從這里連接過來,當轉換失敗時,意味着沒有敵人,我們也要完成完成執行,當然,巡邏狀態下,也要連接到完成執行節點。這個任務的三個選擇最后都要連接到finishExecute節點,因為我們需要這個節點來時外面的序列繼續執行,勾選success,我們最后要添加一個東西來結束這次的視頻,(要做的就是處理錯誤的情況),我們從MoveToActor的輸出端口連線,到Gate節點,添加EventReceiveTick事件,把它連接到Enter端口,把MoveToActor的輸出連接到Open口,然后要做的是添加一個分支節點,繼續添加FinishExecute節點,bSuccess為真,接着把它的輸出連接到Gate的Close節點。如果是false的情況,添加一個SwithchOnEPathFollowingStatus節點,然后我們要得到當前的AI的狀態,我們要從botAI連接,獲得MoveStatus,作為Switch的輸入,獲得狀態,設置為枚舉,val值為2,連接到idle,把這些稍微往后放一下,連接剛剛的到的枚舉和FinishExecute節點,這樣的話,我們就把執行的操作完成了。
最后添加注釋,給兩個finishExecute添加注釋,這樣我們就很容易找到結束的位置, 對中間的邏輯部分添加注釋:朝着敵人移動。這期我們能夠導航AI找到敵人,下一期我們將攻擊敵人!