Quick answer: Add a sense config (e.g. UAISenseConfig_Sight) to the AIPerceptionComponent. Enable “Detect Enemies” and “Detect Neutrals” in affiliation flags. Ensure the target actor is registered as a stimuli source for the relevant sense. If no team IDs are set, actors default to Neutral — check Neutrals is enabled.
Here is how to fix Unreal AI Perception not detecting actors. You add an AIPerceptionComponent to your AI controller or pawn. You configure a sight sense. You run the game and the AI stands there, oblivious to the player standing in front of it. The OnPerceptionUpdated delegate never fires. AI Perception has a chain of requirements — sense config, affiliation, stimuli registration, and team setup — and missing any one of them causes silent detection failure.
The Symptom
The AIPerceptionComponent’s OnPerceptionUpdated or OnTargetPerceptionUpdated delegate never fires. GetCurrentlyPerceivedActors() returns an empty array. The AI debug visualization (EnableDebugDraw) shows the perception radius but no detected actors within it.
Variant: sight works but hearing does not. Or detection works for AI-vs-AI but not AI-vs-player. Or detection fires once and then stops updating.
What Causes This
No sense config added. The AIPerceptionComponent needs at least one sense config object (UAISenseConfig_Sight, UAISenseConfig_Hearing, etc.) to know what to detect. An empty component detects nothing.
Affiliation filter excludes target. Each sense config has three affiliation checkboxes: Detect Enemies, Detect Friendlies, Detect Neutrals. If the target’s team relationship does not match a checked box, it is filtered out before detection logic even runs. Actors without a team ID default to Neutral.
Target not registered as stimuli source. For sight, Pawns are auto-registered. For hearing, damage, and custom senses, the target needs an AIPerceptionStimuliSourceComponent with the relevant sense class enabled, or events must be reported manually via UAISense::ReportEvent.
Perception component on wrong actor. AIPerceptionComponent should be on the AIController or the Pawn. If it is on a random actor that is not possessed or has no AI controller, the perception system may not tick it properly.
Dominant sense not set. The AIPerceptionComponent has a Dominant Sense property. If set incorrectly, the system may prioritize a non-functional sense and ignore the one you configured.
The Fix
Step 1: Add and configure sense config in C++.
// MyAIController.cpp
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Sight.h"
AMyAIController::AMyAIController()
{
PerceptionComp = CreateDefaultSubobject<UAIPerceptionComponent>(
TEXT("PerceptionComp"));
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(
TEXT("SightConfig"));
SightConfig->SightRadius = 1500.0f;
SightConfig->LoseSightRadius = 2000.0f;
SightConfig->PeripheralVisionAngleDegrees = 60.0f;
SightConfig->SetMaxAge(5.0f);
// Critical: enable affiliation detection
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
SightConfig->DetectionByAffiliation.bDetectFriendlies = false;
PerceptionComp->ConfigureSense(*SightConfig);
PerceptionComp->SetDominantSense(SightConfig->GetSenseImplementation());
}
The DetectionByAffiliation flags are the most commonly missed setting. Without Neutrals enabled, unaffiliated players are invisible.
Step 2: Bind the perception delegate.
void AMyAIController::BeginPlay()
{
Super::BeginPlay();
PerceptionComp->OnTargetPerceptionUpdated.AddDynamic(
this, &AMyAIController::OnTargetPerceptionUpdated);
}
void AMyAIController::OnTargetPerceptionUpdated(
AActor* Actor, FAIStimulus Stimulus)
{
if (Stimulus.WasSuccessfullySensed())
{
UE_LOG(LogTemp, Log, TEXT("Detected: %s"),
*Actor->GetName());
}
else
{
UE_LOG(LogTemp, Log, TEXT("Lost: %s"),
*Actor->GetName());
}
}
Step 3: Set up team IDs using IGenericTeamAgentInterface. Without team setup, all actors are team 255 (no team) and treated as Neutral to each other:
// MyAIController.h
class AMyAIController : public AAIController
{
// ...
virtual ETeamAttitude::Type GetTeamAttitudeTowards(
const AActor& Other) const override;
};
// MyAIController.cpp
AMyAIController::AMyAIController()
{
SetGenericTeamId(FGenericTeamId(1)); // AI team
}
ETeamAttitude::Type AMyAIController::GetTeamAttitudeTowards(
const AActor& Other) const
{
auto* TeamAgent = Cast<IGenericTeamAgentInterface>(&Other);
if (TeamAgent && TeamAgent->GetGenericTeamId() == FGenericTeamId(0))
return ETeamAttitude::Hostile;
return ETeamAttitude::Neutral;
}
Set the player’s controller to team 0. The AI (team 1) treats team 0 as Hostile, so “Detect Enemies” now catches the player.
Step 4: Register stimuli sources for non-sight senses. For hearing:
// On the player or noise-making actor, add component in Blueprint
// or in C++:
StimuliSource = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(
TEXT("StimuliSource"));
StimuliSource->RegisterForSense(UAISense_Hearing::StaticClass());
StimuliSource->bAutoRegister = true;
// To emit a noise event:
UAISense_Hearing::ReportNoiseEvent(
GetWorld(), GetActorLocation(), 1.0f,
this, 0.0f, FName("Footstep"));
Debugging AI Perception
Use the AI debug tools at runtime:
// Console command
ai.debug.perception 1
// Or in C++ for a specific controller
PerceptionComp->DrawDebugInfo();
The debug visualization shows sight cones, hearing ranges, and detected actors with colored indicators (green = currently sensed, red = lost). If the cone appears but nothing highlights inside it, affiliation or stimuli registration is the problem.
“Sense config, affiliation flags, stimuli source. Three links in the perception chain. Break any one and the AI is blind.”
Related Issues
For actor replication in multiplayer AI, see Actor Replication Not Working. For behavior tree integration with perception, GameplayAbility Not Activating covers related AI activation patterns.
ConfigureSense, enable Neutrals in affiliation, register stimuli. Then the AI can finally see.