How to do it...

  1. Open up your .Build.cs file (in our case, Chapter_13.Build.cs) and add the following dependencies:
using UnrealBuildTool;

public class Chapter_13 : ModuleRules
{
public Chapter_13(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" });
PublicDependencyModuleNames.AddRange(new string[] { "AIModule", "GameplayTasks" });

}
}
  1. Compile your code. 
  2. From the Content Browser, select Add New | New C++ Class. At the Add C++ Class menu, check the Show All Classes option type in AIController, and then select the AIController class. Then, click on Next:

  1. When asked for a name for the class, name it EnemyAIController and click on the Create Class button.
  1. Open up Visual Studio and update the EnemyAIController.h file to the following:
#pragma once

#include "CoreMinimal.h"
#include "AIController.h"
#include "BehaviorTree/BehaviorTreeComponent.h"
#include "BehaviorTree/BlackboardComponent.h"

#include "EnemyAIController.generated.h"

/**
*
*/
UCLASS()
class CHAPTER_13_API AEnemyAIController : public AAIController
{
GENERATED_BODY()

private:
// AI Component references
UBehaviorTreeComponent* BehaviorComp;
UBlackboardComponent* BlackboardComp;

public:
AEnemyAIController();

// Called when the controller possesses a Pawn/Character
virtual void Possess(APawn* InPawn) override;

FBlackboard::FKey TargetKeyID;


};

  1. After creating the function declarations, we need to define them in the EnemyAIController.cpp file:
#include "EnemyAIController.h"

AEnemyAIController::AEnemyAIController()
{
//Initialize components
BehaviorComp = CreateDefaultSubobject<UBehaviorTreeComponent>(TEXT("BehaviorComp"));
BlackboardComp = CreateDefaultSubobject<UBlackboardComponent>(TEXT("BlackboardComp"));
}

// Called when the controller possesses a Pawn/Character
void AEnemyAIController::Possess(APawn* InPawn)
{
Super::Possess(InPawn);
}

In addition to an AI Controller, we also need to have a Character. 

  1. Create a new C++ class that derives from Character by going to Add New | New C++ Class. Under the Add C++ Class menu, select Character and hit the Next button:

  1. From the next screen, Name the class EnemyCharacter and click on the Create Class button.
  1. Open Visual Studio. Under the EnemyCharacter.h file, add the following property:
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "EnemyCharacter.generated.h"

UCLASS()
class CHAPTER_13_API AEnemyCharacter : public ACharacter
{
GENERATED_BODY()

public:
// Sets default values for this character's properties
AEnemyCharacter();

UPROPERTY(EditAnywhere, Category = Behavior)
class UBehaviorTree *EnemyBehaviorTree;

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;

// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};
  1. Then, we can go back into the EnemyAIController.cpp file and update the Possess function since our Character class exists:
#include "EnemyAIController.h"
#include "EnemyCharacter.h"
#include "BehaviorTree/BehaviorTree.h"


AEnemyAIController::AEnemyAIController()
{
// Initialize components
BehaviorComp = CreateDefaultSubobject<UBehaviorTreeComponent>(TEXT("BehaviorComp"));
BlackboardComp = CreateDefaultSubobject<UBlackboardComponent>(TEXT("BlackboardComp"));
}

// Called when the controller possesses a Pawn/Character
void AEnemyAIController::Possess(APawn* InPawn)
{
Super::Possess(InPawn);

// Convert InPawn to EnemyCharacter
auto Character = Cast<AEnemyCharacter>(InPawn);

// Check if pointers are valid
if(Character && Character->EnemyBehaviorTree)
{
BlackboardComp->InitializeBlackboard(*Character->EnemyBehaviorTree->BlackboardAsset);

TargetKeyID = BlackboardComp->GetKeyID("Target");

BehaviorComp->StartTree(*Character->EnemyBehaviorTree);
}
}
  1. Save your scripts and compile your code.

Now, we will create a Blueprint version of the two classes we just created and assign our variables.

  1. From the Content Browser under the C++ Classes/Chapter_13 folder, right-click on the EnemyAIController object and select the Create Blueprint class based on EnemyAIController option. Give it a name and click on the Create Blueprint Class button.
  2. Likewise, do the same thing for the EnemyCharacter object.
  1. Double-click on your MyEnemyCharacter Blueprint and, under the Details tab, set the Enemy Behavior Tree property to EnemyBehaviorTree. Then, set the AI Controller Class property to MyEnemyAIController:

Assigning the Enemy Behavior Tree and AI Controller Class properties
  1. You'll likely want a visual component for the character as well, so from the Components tab, click on the Add Component button and select Cube. Afterward, modify the Scale to (0.5, 0.5, 1.5). 

As we discussed previously, you may need to click on the Open Full Blueprint Editor text to see all of the available options.

16. Then, hit Compile and save all of your assets:

The completed enemy character

And with that, we've set up a connection between an AI Character, an AI Controller, and a Behavior Tree!