거의 대부분의 AI Perception 강의에서 AI Perception Component를 블루프린트에서 추가해 사용하길레 의문이 들었다. 왜냐하면, AI Controller 클래스 자체에 이미 AI Perception Component가 PerceptionComponent 라는 이름으로 선언되어있고 Get/Set 함수 모두 제공되고 있기 때문이다.

그래서 나도 그냥 CreateDefaultSubobject로 컴포넌트를 넣어 사용하려 했는데, 블루프린트 서브 클래스로 뽑아보니 붙어는 있는데 Sight Config을 넣어 테스트 하려는데 Detection by Affiliation 카테고리 속에 아무런 아이템도 없었다.

엔진 버그였다.

https://answers.unrealengine.com/questions/602376/perception-component-added-in-c-wont-allow-senses.html

아직도 이유는 잘 모르겠는데, 일단 코드상에서 보면 UAISenseConfig_Sight를 두고 거기서 설정을 해둔 다음에 ConfigueSense함수에 넣어 처리해줘야하는 것 같다.

헤더

#pragma once

#include "CoreMinimal.h"
#include "AIController.h"
#include "NPC_AIController.generated.h"

UCLASS()
class TEST_API ANPC_AIController : public AAIController
{
	GENERATED_BODY()
	
public:
	ANPC_AIController();

private:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	float AISightRadius = 500.0f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	float AISightAge = 5.0f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	float AILoseSightRadius = AISightRadius + 50.0f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	float AIFieldOfView = 90.0f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
	class UAISenseConfig_Sight* SightConfig;

	virtual void BeginPlay() override;
};

구현부

#include "NPC_AIController.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Sight.h"

ANPC_AIController::ANPC_AIController()
{
	SetPerceptionComponent(*CreateOptionalDefaultSubobject<UAIPerceptionComponent>(TEXT("AI Perception")));
	SightConfig = CreateOptionalDefaultSubobject<UAISenseConfig_Sight>(TEXT("Sight Config"));

	SightConfig->SightRadius = AISightRadius;
	SightConfig->LoseSightRadius = AILoseSightRadius;
	SightConfig->PeripheralVisionAngleDegrees = AIFieldOfView;
	SightConfig->SetMaxAge(AISightAge);

	SightConfig->DetectionByAffiliation.bDetectEnemies = true;
	SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
	SightConfig->DetectionByAffiliation.bDetectFriendlies = true;

	GetPerceptionComponent()->SetDominantSense(*SightConfig->GetSenseImplementation());
	GetPerceptionComponent()->ConfigureSense(*SightConfig);
}

void ANPC_AIController::BeginPlay()
{
	Super::BeginPlay();
}

엔진을 뜯어보니

AI Perception이 없으면 찾아서 알아서 부착해준다. 그냥 이런건 블루프린트 쪽에서 처리하는게 나을수도 있어 보인다.

void AAIController::PostRegisterAllComponents()
{
	Super::PostRegisterAllComponents();

	// cache PerceptionComponent if not already set
	// note that it's possible for an AI to not have a perception component at all
	if (PerceptionComponent == NULL || PerceptionComponent->IsPendingKill() == true)
	{
		PerceptionComponent = FindComponentByClass<UAIPerceptionComponent>();
	}
}