AAIController class in Unreal Engine

AAIController class. What, Why, How? A Guide for AI with AAIController class in Unreal engine.

AIController is the base class of controllers for AI-controlled Pawns.

While the PlayerController relies on the human player to make decisions on what to do, the AIController is more focused on responding to input from the environment and game world. The job of the AIController is to observe the world around it and make decisions and react accordingly without explicit input from a human player.

Inheritance Hierarchy

It may be handy to use the AIController with Artificial InteligenceBehavior Tree and Blackboard tools.

// .h file
class UBehaviorTree* AIBehavior;

// .cpp file
#include "BehaviorTree/BlackboardComponent.h"
void AExampleAIController::BeginPlay()
{
    Super::BeginPlay();
    if(AIBehavior != nullptr) RunBehaviorTree(AIBehavior);
}
void AExampleAIController::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);
	// All the code below can be moved to BTT serice - see the BTTService example below
	APawn *PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
	if(LineOfSightTo(PlayerPawn)){
		GetBlackboardComponent()->SetValueAsVector(TEXT("PlayerLocation"), PlayerPawn->GetActorLocation());
	} else {
		GetBlackboardComponent()->ClearValue(TEXT("PlayerLocation"));
	}
}

BTT services

With using a Behavior Tree, there's possible to create own custom C++ UBTServices (New C++ ClassBTService_BlackboardBase (through show all classes)). Then, we can place it in necessary places in the Behavior Tree logic and avoid of processing certain task (updating a value in this case) only when it's necessary for the right function logic.

// .h file
UCLASS()
class ExampleApp_API UBTService_PlayerLocationIfSeen : public UBTService_BlackboardBase
{
    GENERATED_BODY()
public:
	UBTService_PlayerLocation();
protected:
    virtual void TickNode(UBehaviorTreeComponent &OwnerComp, uint8 *NodeMemory, float DeltaSeconds) override;
}

// .cpp file
#include "BehaviorTree/BlackboardComponent.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/Pawn.h"
#include "AIController.h"

UBTService_PlayerLocationIfSeen::UBTService_PlayerLocationIfSeen()
{
	NodeName = "Update Player Location If Seen";
}

void UBTService_PlayerLocationIfSeen::TickNode(UBehaviorTreeComponent &OwnerComp, uint8 *NodeMemory, float DeltaSeconds)
{
    Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
    APawn *PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
	if(PlayerPawn == nullptr) return;
	if(OwnerComp.GetAIOwner() == nullptr) return;
	if(OwnerComp.GetAIOwner() ->LineOfSightTo(PlayerPawn))
	{
		// For Vectors
		OwnerComp.GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), PlayerPawn->GetActorLocation());
		// For Objects
		OwnerComp.GetBlackboardComponent()->SetValueAsObject(GetSelectedBlackboardKey(), PlayerPawn);
	} else {
		OwnerComp.GetBlackboardComponent()->ClearValue(GetSelectedBlackboardKey());
	}
}