I think UAIPerceptionComponent::ConfigureSense is not working properly. For some reason, it’s not calling RequestStimuliListenerUpdate(). When I step through the code and try to step into the RequestStimuliListenerUpdate() function, it goes straight to UActorComponent::GetWorld().
I ran into this issue because my hearing perception would not trigger. After stepping through the code, I realized that UAISense_Hearing::Update() was exiting out early because the FPerceptionListener did not have the hearing sense. I can only get the hearing perception to trigger if I manually call UAIPerceptionComponent::UpdatePerceptionWhitelist in order to add the hearing sense to the perception listener (which should already be done by ConfigureSense).
I thought this might be specific to my engine build, so I made a blank project from the release build. I still had the same problem with getting the hearing perception to trigger. Again, manually calling UpdatePerceptionWhitelist allowed the hearing perception to trigger, so I think there’s an issue with the official release.
There might also be an issue with the UAIPerceptionComponent::SensesConfig array member as well. I noticed that sight perception was able to trigger even though hearing was not. For some reason, the SensesConfig array already contains a UAISenseConfig_Sight value before registering the component, so it’s able to update the the perception listener with the sight config during UAIPerceptionComponent::OnRegister(). But I think that sight config value is nulled out somewhere between the constructor and the begin play phase, because I was running into some really weird errors. The SensesConfig array would have proper sense config values during construction but null sense config values during BeginPlay and my editor would crash trying to access the invalid addresses.
Lastly, I think the FPerceptionUpdatedDelegate should use const TArray& instead of TArray as its parameter type. Else, BlueprintNativeEvents bound to this delegate will cause compilation errors since the compiler gets confused about the TArray type. Is there a good reason why it’s not?
Hopefully my explanations aren’t too confusing. Maybe someone can try to reproduce these issues. Thanks!
Here’s my code sample for the AIController:
[AMyAIController.h]
#pragma once
#include "AIController.h"
#include "Perception/AiPerceptionComponent.h"
#include "Perception/AISenseConfig_Hearing.h"
#include "Perception/AISense_Hearing.h"
#include "MyAIController.generated.h"
/**
*
*/
UCLASS()
class TESTPROJECT_API AMyAIController : public AAIController
{
GENERATED_BODY()
public:
AMyAIController();
virtual void BeginPlay() override;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "AI")
UAIPerceptionComponent* AIPerception;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "AI")
UAISenseConfig_Hearing* HearingConfig;
UFUNCTION(BlueprintCallable, Category = "AI")
void PerceptionUpdated(TArray<AActor*> UpdatedActors);
};
[AMyAIController.cpp]
#include "TestProject.h"
#include "MyAIController.h"
AMyAIController::AMyAIController()
{
// Setup the perception component
AIPerception = GetAIPerceptionComponent();
AIPerception = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("AIPerception Component"));
HearingConfig = CreateDefaultSubobject<UAISenseConfig_Hearing>(TEXT("Hearing Config"));
}
void AMyAIController::BeginPlay()
{
Super::BeginPlay();
HearingConfig->HearingRange = 10000.f;
HearingConfig->DetectionByAffiliation.bDetectEnemies = true;
HearingConfig->DetectionByAffiliation.bDetectNeutrals = true;
HearingConfig->DetectionByAffiliation.bDetectFriendlies = true;
AIPerception->ConfigureSense(*HearingConfig);
AIPerception->SetDominantSense(HearingConfig->GetSenseImplementation());
AIPerception->OnPerceptionUpdated.AddDynamic(this, &AMyAIController::PerceptionUpdated);
// Uncomment this to get the hearing perception to actually trigger
//AIPerception->UpdatePerceptionWhitelist(HearingConfig->GetSenseID(), true);
UAIPerceptionSystem::RegisterPerceptionStimuliSource(this, HearingConfig->GetSenseImplementation(), GetPawn());
}
void AMyAIController::PerceptionUpdated(TArray<AActor*> UpdatedActors)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, FString::Printf(TEXT("Perception")));
}