用UE4制作一個(gè)簡(jiǎn)單的AI小游戲

UnrealEngine是一個(gè)非常強(qiáng)大的引擎,UE4基于DirectX11哥捕,擁有新的材料流水線(xiàn)牧抽、藍(lán)圖視覺(jué)化腳本、直觀(guān)藍(lán)圖調(diào)試遥赚、內(nèi)容瀏覽器、人物動(dòng)畫(huà)阐肤、Matinee影院級(jí)工具集凫佛、后期處理效果、熱重載孕惜、模擬與沉浸式視角愧薛、實(shí)時(shí)游戲預(yù)覽、AI人工智能衫画、音頻毫炉、中間件集成等一系列全新特性。
下面是用C++結(jié)合藍(lán)圖實(shí)現(xiàn)一個(gè)簡(jiǎn)單的AI功能削罩。效果如下圖

  • 首先創(chuàng)建一個(gè)C++的第三人稱(chēng)工程瞄勾,UE4的工程有很多類(lèi)型,我們可以根據(jù)自己的需要選擇弥激。

  • 然后新建需要的C++文件进陡,包括AIPatrol、AIPatrolController微服、AI巡邏的目標(biāo)點(diǎn)AITargetPoint趾疚,類(lèi)型分別為Character、Controller以蕴、TargetPoint糙麦。

  • 將上述三個(gè)文件擴(kuò)展成藍(lán)圖,這樣C++和藍(lán)圖可以結(jié)合起來(lái)丛肮,比較方便的實(shí)現(xiàn)一些功能赡磅。

  • 新建BehaviorTree、Blackboard腾供。行為樹(shù)用來(lái)實(shí)現(xiàn)AI的邏輯仆邓。
    ![T98AAKVRE6]OVK5(AWG0A.png](http://upload-images.jianshu.io/upload_images/1765742-312a11011d4cc53f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  • 在AIPatrol上加BehaviorTree:

      UPROPERTY(EditAnywhere,Category=AI)//add behavior to character
      class UBehaviorTree* BehaviorTree;
  • 配置character的參數(shù)
characer.png

![($$_]V}CV$-GAEQ5IIO7MOE.png](http://upload-images.jianshu.io/upload_images/1765742-ad8ce6fb1d799c49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  • AIPatrolController
    .h文件:
             /*behavior tree component*/
            UBehaviorTreeComponent* BehaviorComp;

             /*Our blackboard component*/
             UBlackboardComponent* BlackboardComp;

             /*Blackboard keys*/
             UPROPERTY(EditDefaultsOnly, Category = AI)
                    FName LocationToGoKey;

             UPROPERTY(EditDefaultsOnly, Category = AI)
                    FName PlayerKey;

             //store all TargetPoints
             TArray<AActor*> PatrolPoints;

             virtual void Possess(APawn* Pawn) override;
public:
      AAIPatrolController();

      void SetPlayerCaught(APawn* Pawn);//caught:捕捉

      /*Inline getter functions*/
      FORCEINLINE UBlackboardComponent* GetBlackboardComp() const { return BlackboardComp; }
      FORCEINLINE TArray<AActor* > GetPatrolPoints() const { return PatrolPoints; }

.cpp文件:

AAIPatrolController::AAIPatrolController()
{
       /*initialize blackboard and behavior tree*/
       BehaviorComp = CreateDefaultSubobject<UBehaviorTreeComponent>(TEXT("BehaviorComp"));
       BlackboardComp = CreateDefaultSubobject<UBlackboardComponent>(TEXT("BlackboardComp"));

       /*Initialize blackboard keys*/
       PlayerKey = "Target";
       LocationToGoKey = "LocationToGo";
}

void AAIPatrolController::SetPlayerCaught(APawn* MyPawn)
{
       if (BlackboardComp)
       {
              BlackboardComp->SetValueAsObject(PlayerKey, MyPawn);
       }
}

void AAIPatrolController::Possess(APawn* MyPawn)
{
       Super::Possess(MyPawn);

       /*Get reference to the character*/
       AAIPatrol* AICharacter = Cast<AAIPatrol>(MyPawn);
       if (AICharacter)
       {
              if (AICharacter->BehaviorTree->BlackboardAsset)
              {
                     BlackboardComp->InitializeBlackboard(*(AICharacter->BehaviorTree->BlackboardAsset));
              }

              /*Populate patrol point array*/
              UGameplayStatics::GetAllActorsOfClass(GetWorld(), AAIpPatrolPoint::StaticClass(), PatrolPoints);

              BehaviorComp->StartTree(*AICharacter->BehaviorTree);

       }
}
  • 玩家被抓住的方法:
    AIPatrolController:
void AAIPatrolController::SetPlayerCaught(APawn* MyPawn)//玩家被抓住
{
       if (BlackboardComp)
       {
              BlackboardComp->SetValueAsObject(PlayerKey, MyPawn);//給玩家添加key值
       }
}

AIPatrol:

AAIPatrol::AAIPatrol()
{
       //Initialize senses
       /**UPawnSensingComponent :
       * SensingComponent encapsulates(封裝) sensory(感知) (ie sight and hearing) settings and functionality for an Actor,
       * allowing the actor to see/hear Pawns in the world. It does nothing on network clients.
       */
       PawnSensingComp = CreateDefaultSubobject<UPawnSensingComponent>(TEXT("PawnSensingComp"));
       PawnSensingComp->SetPeripheralVisionAngle(90.0f);

}

// Called when the game starts or when spawned
void AAIPatrol::BeginPlay()
{
       Super::BeginPlay();

       if (PawnSensingComp)
       {
              /** OnSeePawn : Delegate to execute when we see a Pawn. */
              PawnSensingComp->OnSeePawn.AddDynamic(this, &AAIPatrol::OnplayerCaught);
       }
}

void AAIPatrol::OnplayerCaught(APawn* Pawn)
{
       /*Get a reference to the palyer controller*/
       AAIPatrolController* AIController = Cast<AAIPatrolController>(GetController());
       if (AIController)
       {
              GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("You having been caught!"));
              AIController->SetPlayerCaught(Pawn);
       }
}

* 創(chuàng)建BTTask的C++文件鲜滩,命名為BTSelectPatrolPoint。注意节值,這時(shí)要在Source文件夾中找到ProjectName.Build.cs文件徙硅,添加GameplayTasks到PublicDependencyModuleName中。.build.cs文件是編譯文件搞疗,位于游戲性模塊的根目錄中嗓蘑,它定義了UnrealBuildTool編譯該模塊時(shí)要使用的一些信息。

29%{%@ZZL4N(}(LQYU5D-TF.png

BTTask:

EBTNodeResult::Type UBTSelectPatrolPoint::ExecuteTask(UBehaviorTreeComponent & OwnerComp, uint8 * NodeMemory)
{

       //get AIPatrolController
       AAIPatrolController* AICon = Cast<AAIPatrolController>(OwnerComp.GetAIOwner());

       // check the get is successful
       if (AICon)
       {
              //Get Blackboard Component
              UBlackboardComponent* BlackboardComp = AICon->GetBlackboardComp();

              // get patrolPoint
              AAIpPatrolPoint* CurrentPoint = Cast<AAIpPatrolPoint>(BlackboardComp->GetValueAsObject("LocationToGo"));

              TArray<AActor*> AvailablePatrolPoints = AICon->GetPatrolPoints();
              AAIpPatrolPoint* NextPatrolPoint = nullptr;

              // set NextPatrolPoint
              if (AICon->CurrentPatrolPoint != AvailablePatrolPoints.Num() - 1)
              {
                     NextPatrolPoint = Cast<AAIpPatrolPoint>(AvailablePatrolPoints[++AICon->CurrentPatrolPoint]);
              }
              else
              {
                     NextPatrolPoint = Cast<AAIpPatrolPoint>(AvailablePatrolPoints[0]);
                     AICon->CurrentPatrolPoint = 0;
              }

              // set blackboard keyValue
              BlackboardComp->SetValueAsObject("LocationToGo", NextPatrolPoint);
              return EBTNodeResult::Succeeded;
       }
       return EBTNodeResult::Failed;

}
  • 將BP_AIPatrol放入場(chǎng)景匿乃,擺放好BP_AIPatrolPoints桩皿,即AI 要走的路徑,編輯BehaviorTree幢炸。
374539dd-5422-4ed9-b45d-5673aabe9863.png

BehaviorTree的思路是首先執(zhí)行BTSelectPatrolPoint泄隔,如果沒(méi)有找到目標(biāo),就move to key值為L(zhǎng)ocationToGo的點(diǎn)宛徊,如果找到了Target佛嬉,就移動(dòng)到Target處,然后在target處停留1秒闸天。

  • 最后暖呕,添加自動(dòng)尋路組件NavMeshBoundsVolume,這樣AI在尋路過(guò)程中就會(huì)自動(dòng)繞開(kāi)障礙物苞氮。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末湾揽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子笼吟,更是在濱河造成了極大的恐慌库物,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赞厕,死亡現(xiàn)場(chǎng)離奇詭異艳狐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)皿桑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)毫目,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人诲侮,你說(shuō)我怎么就攤上這事镀虐。” “怎么了沟绪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵刮便,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绽慈,道長(zhǎng)恨旱,這世上最難降的妖魔是什么辈毯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮搜贤,結(jié)果婚禮上谆沃,老公的妹妹穿的比我還像新娘。我一直安慰自己仪芒,他們只是感情好唁影,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掂名,像睡著了一般据沈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饺蔑,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天锌介,我揣著相機(jī)與錄音,去河邊找鬼膀钠。 笑死掏湾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肿嘲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼筑公,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雳窟!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起匣屡,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤封救,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后捣作,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體誉结,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了以舒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖世分,靈堂內(nèi)的尸體忽然破棺而出罚攀,到底是詐尸還是另有隱情雌澄,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布畦浓,位于F島的核電站祷嘶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嘉汰。R本人自食惡果不足惜荧降,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邓梅。 院中可真熱鬧掖看,春花似錦、人聲如沸哎壳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)归榕。三九已至尸红,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刹泄,已是汗流浹背外里。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留特石,地道東北人盅蝗。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像姆蘸,于是被迫代替她去往敵國(guó)和親风科。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉乞旦,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評(píng)論 0 9
  • 前排看文檔啦,看懂了就不用看下面這些廢話(huà)啦:https://docs.unrealengine.com/lates...
    廿十浮城閱讀 7,619評(píng)論 5 13
  • 本教程旨在教會(huì)大家如何為YGOPro編寫(xiě)或修改一個(gè)AI腳本题山。前幾節(jié)是新手指引兰粉,而接下來(lái)的章節(jié)涵蓋了一些更深入的知識(shí)...
    e26h閱讀 13,095評(píng)論 2 9
  • 有時(shí)候你會(huì)猶豫是不是這人 多考慮考慮 不會(huì)有錯(cuò)的
    得水kim閱讀 277評(píng)論 0 0
  • 最直觀(guān)的是 : get將所要傳送的數(shù)據(jù),包裹在url中 post則是將數(shù)據(jù)放入request body中 【get...
    Ann_l閱讀 1,132評(píng)論 0 0