Ok, so for me, the only way I found is to have the AI Perception component in the controller, set the dominant sense, but not add any sense config in the blueprint.
Then in code I register the sense with the cofiguration already correct.
That way it is always correct and doesn’t need to be changed.
In my AI Controller, I control how to call this with an extra validation.
Add a counter to the controller, set to 0.
Create your custom event and check if the counter is equal 2, if not just ignores, if it is, call your c++ register function;
On begin play, you add 1.
On possess you add 1.
In this case, I’m setting the radius before starting my State tree, so that is why the function is named Init state tree, but doesn’t metter, as long you call your c++ register where you register your sense with the correct configuration already.
This guarantee that both controller and pawn will exists already, and you can read your pawn properties to get what attributes you need to calculate the sense.
the only annoying part as changing in runtine means, removing the AI Perception, and adding a new one, then calling the reigster again. I could not get it to update at runtime without this. If you go this route, remember to re-bind the events as it will get lost
UCLASS()
class YourClass_API ABaseDetourAiController : public ADetourCrowdAIController{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void setSightRange(float seeRange, float loseRange);
}
void ABaseDetourAiController::setSightRange(float seeRange, float loseRange) {
if (UAIPerceptionComponent* Perception = GetAIPerceptionComponent()) {
UAISenseConfig_Sight* SightConfig = NewObject<UAISenseConfig_Sight>(this);
SightConfig->PeripheralVisionAngleDegrees = 180;
SightConfig->SightRadius = seeRange;
SightConfig->LoseSightRadius = loseRange;
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
SightConfig->DetectionByAffiliation.bDetectFriendlies = true;
SightConfig->SetStartsEnabled(true);
Perception->ConfigureSense(*SightConfig);
UAIPerceptionSystem::GetCurrent(this)->RegisterSenseClass(UAISense_Sight::StaticClass());
UKismetSystemLibrary::PrintString(GetWorld(), FString("Sight sense registered"), true, true, FColor::Green, 10.f);
Perception->RequestStimuliListenerUpdate();
return;
}
UKismetSystemLibrary::PrintString(GetWorld(), FString("Sight sense failed to register"), true, true, FColor::Red, 10.f);
}
I’m passing the parameters here, but you could as well just read from the pawn directly or anywhere you have your paramters;