In this lesson, you will learn how to identify and refactor expensive operations within your PlayerController to ensure your game maintains a smooth frame rate.
The Cost of the Tick
In Unreal Engine, the Tick function runs every single frame. Because the PlayerController is the "brain" of your player, it is tempting to place logic there—like checking for nearby enemies or updating UI elements. However, if your controller performs heavy math or complex object searches every frame, it will quickly become a performance bottleneck.
Identifying "Heavy" Operations
The most common performance killers in a controller are:
GetAllActorsOfClass: Searching the entire world for specific actors is computationally expensive. Doing this every tick will cause massive lag.- Complex Raycasting: Running high-precision line traces every frame for non-essential gameplay logic.
- Heavy String Manipulation: Logging, printing strings, or formatting text inside
Tick.
Refactoring Logic
Instead of checking for conditions every frame, you should use Events and Timers.
For example, if you want your controller to check if the player is near a quest objective, don’t run a check every frame. Instead, use an Overlap Event or a Timer that runs only a few times per second.
Consider this inefficient approach:
// Inefficient: Checking every frame (Tick)
void AMyPlayerController::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
// Searching the whole world every frame is very slow!
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AObjective::StaticClass(), FoundActors);
// ... logic follows
}
Instead, use a Timer to trigger the check only when needed:
// Efficient: Using a timer
void AMyPlayerController::BeginPlay() {
Super::BeginPlay();
// Only check every 0.5 seconds
GetWorldTimerManager().SetTimer(TimerHandle, this, &AMyPlayerController::CheckObjectives, 0.5f, true);
}
By moving logic out of Tick and into timers or triggered events, you prevent the controller from wasting CPU cycles on tasks that don’t need to happen 60+ times per second.
Key Takeaway: Never perform heavy searches or calculations inside the Tick function; move these operations to Timers or Event-based triggers to keep your controller logic performant.