Got a little treat to share for any of you working w/ large levels & large AI counts. Enables/Disables AI processes, as needed. This saved me about 4.6ms:
void APFAIController::UpdateAIProcessCulling()
{
if (PFCPawn.IsValid())
{
APFGameState* PFGS = Cast<APFGameState>(GetWorld()->GetGameState());
// Check nearest enemy distance (not just player locations cause AI fight other AI)
TArray<APFCharacter*> enemyList;
PFGS->GetEnemyPawns(this, enemyList);
float closestDistSq = BIG_NUMBER;
for (int i = 0; i < enemyList.Num(); ++i)
{
const float distSq = (PFCPawn->GetActorLocation() - enemyList*->GetActorLocation()).SizeSquared();
if (distSq < closestDistSq)
{
closestDistSq = distSq;
}
}
const bool bWantsKillProcesses = !PFCPawn->WasRecentlyRendered() && closestDistSq > FMath::Square(processCullingDistance);
if (IsActorTickEnabled() == bWantsKillProcesses)
{
// Enable/Disable movement component
UPFCharacterMovementComponent* PFCMC = PFCPawn->GetPFCharacterMovement();
if (PFCMC->MovementMode != EMovementMode::MOVE_None)
{
PFCMC->SetActive(!bWantsKillProcesses);
PFCMC->SetComponentTickEnabled(!bWantsKillProcesses);
}
// Enable/Disable sight/sound/damage senses
GetAIPerceptionComponent()->SetActive(!bWantsKillProcesses);
GetAIPerceptionComponent()->SetComponentTickEnabled(!bWantsKillProcesses);
SetBehaviorTreePaused(bWantsKillProcesses);
// For good measure, kill weapon tick, too...
AWeapon* equippedWeapon = PFCPawn->Inventory->GetEquippedWeapon();
if (equippedWeapon != nullptr)
{
equippedWeapon->SetActorTickEnabled(!bWantsKillProcesses);
}
// Controller & pawn should both get their ticks updated
SetActorTickEnabled(!bWantsKillProcesses);
PFCPawn->SetActorTickEnabled(!bWantsKillProcesses);
}
}
}