Perception component - OnPerceptionUpdated not called

Hello, I am playing with perception component but OnPerceptionUpdated is not working for me - it is never called.

MyAIController constructor:



UMyAIPerceptionComponent* pc = CreateDefaultSubobject<UMyAIPerceptionComponent>(TEXT("AIPerception"));
SetPerceptionComponent(*pc);
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("AISightConfig"));


MyAIController::Possess


	
        UAIPerceptionComponent* pc = GetAIPerceptionComponent();
	if (pc)
	{
		UE_LOG(LogTemp, Warning, TEXT("perception component created: %s"), *GetName());

		if (SightConfig)
		{
			SightConfig->SightRadius =     500;
			SightConfig->LoseSightRadius = 550;
			SightConfig->PeripheralVisionAngleDegrees = 90.0f;
			SightConfig->DetectionByAffiliation.bDetectEnemies = true;
			SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
			SightConfig->DetectionByAffiliation.bDetectFriendlies = true;
		}

		pc->ConfigureSense(*SightConfig);
		pc->OnPerceptionUpdated.AddDynamic(this, &AMyAIController::OnPerceptionUpdated);
		pc->OnTargetPerceptionUpdated.AddDynamic(this, &AMyAIController::OnTargetPerceptionUpdated);
	}


AMyPlayer constructor



PerceptionSource = CreateDefaultSubobject<UMyAIPerceptionSourceComponent>(TEXT("AIPerceptionSource"));


AMyPlayer::PossessedBy



UAIPerceptionSystem::RegisterPerceptionStimuliSource(this, UAISense_Sight::StaticClass(), this);


I inherited custom class from PerceptionSystem and I checked GetListenersMap.Num() and RegisteredStimuliSources.Num().
Listeners follow number of my PerceptionComponent obejcts but stimuli sources are still 0.
I tried to implement my own register function where I call RegisterPerceptionStimuliSource and PerformSourceRegistartion - stimuli sources then follow number of my PerceptionSourceComponent objects.
However OnPerceptionUpdated is still not called.



void UMyAIPerceptionSystem::LogID()
{
	uint32 id = GetUniqueID();
	int32 ln = GetListenersMap().Num();
	int32 sn = RegisteredStimuliSources.Num();
	UE_LOG(LogTemp, Warning, TEXT("ps-id: %d listeners: %d sources: %d"), id, ln, sn);
}

void UMyAIPerceptionSystem::Register(AActor & SourceActor)
{
	RegisterSight();

	// works
	//RegisterSource<UAISense_Sight>(SourceActor);
	
	//works
	UAIPerceptionSystem::RegisterPerceptionStimuliSource(this, UAISense_Sight::StaticClass(), &SourceActor);

	PerformSourceRegistration();

	LogID();
}


Any ideas?

Probably not the solution to your problem, but how close do you get to your AI? The sight-radius is set to five meters; that might just be to small, depending on the size of the AI-controlled Pawn and your distance to it.

Aside from that your code looks good to me.

The event you are trying to have triggered does not depend on GetListenersMap.Num(). It depends on UpdatedActors.Num() at one point as seen here in the ProcessSimuli() method of the AIPerceptionComponent:


StimuliToProcess.Reset();

	if (UpdatedActors.Num() > 0)
	{
		if (AIOwner != NULL)
		{
			AIOwner->ActorsPerceptionUpdated(UpdatedActors);
		}

		OnPerceptionUpdated.Broadcast(UpdatedActors);
	}

This is the last block of code ran in that method. This is also the only area that this is called in the entire component.

The array that we are looking at to determine whether or not to run the updated code has values added to it a few lines above that, found here:


		if (SourcedStimulus->Stimulus.WasSuccessfullySensed() || StimulusStore.WasSuccessfullySensed())
		{
			UpdatedActors.AddUnique(SourcedStimulus->Source);
		}

So we can see that the event is only ever called if there is something in the array and something is only ever added to the array if either one or two boolean returning functions return true. So, I would start looking into that code, the boolean returning functions (WasSuccessfullySensed()) and see where they return true and make sure you meet those requirements.

tcld: Thx for the tip, I tried different values but it didn’t helped. My meshes are attached to capsule components with half height set to 100 and radius set to 50 so it should be fine.

smartyMARTY: Thx for the tip, do I need to call ProcessSimuli or RequestStimuliListenerUpdate somewhere?

I don’t think so (on tablet right now so no easy access to source code.) But I have a question, your AMyPlayer class has the Controller configured to an AIController or subclass of that, correct?

AMyPlayer is using controller inherited from APlayerController.
And about AIController, in AMyPlayer ctor I do this:



	AIControllerClass = nullptr;


I inherit AMyAPlayer from AMyCharacter where I do this:



 	AIControllerClass = AMyAIController::StaticClass();


I add more and more log messages and I just noticed that following code logs that only player has controller, other two pawns representing enemies returns null for GetController call.
( enemies have set ‘Auto posses AI’ to ‘Placed in world or spawn’ and I am getting log message which shows MyAIController was created )



void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();

	AController* controller = GetController();

	if (controller)
	{
		UE_LOG(LogTemp, Warning, TEXT("%s has controller: %s"), *GetName(), *controller->GetName());
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("%s has no controller!"), *GetName());
	}
}


Thx for resposne!

Still checking my code.
I fount that if I set AIControllerClass in MyCharacter’s constructor, then pawn is added to AIPerceptionSystem as a listener ( UMyAIPerceptionSystem->GetListenersMap().Num() > 0 ).
And if I check character controller in it’s BeginPlay it is not set as I described in my previous reply ( GetController() returns nullptr ).
If I do not set AIControllerClass, then pawn is not added to AIPerceptionSystem as a listener but controller is correctly set.

Perhaps taking a look at this link would help as it sounds like you are having the same issue:

https://answers.unrealengine.com/questions/51957/how-to-get-aicontroller-from-pawn.html

Also, I have seen that if you try casting the GetController() call to either AIController or PlayerController, it works, or something like that.

I hope this helps. Usually I don’t bother to configure the AI in C++, rather just in the Blueprints and I have not had issues with it.