| title | Unreal Engine Performance Guidelines | |||||||
|---|---|---|---|---|---|---|---|---|
| author | CodeGameDevCommon | |||||||
| type | skill-file | |||||||
| tags |
|
|||||||
| version | 1.0.0 | |||||||
| description | A comprehensive checklist and guide for diagnosing and fixing performance bottlenecks in Unreal Engine, structured for both developers and AI workhorse models. |
tldr; Before you optimize anything in Unreal Engine, find out exactly what is slowing you down by using stat unit. Figure out if you are Game Thread (CPU) bound, Draw Thread (CPU) bound, or GPU bound. Once identified, ruthlessly eliminate Blueprint Ticks, leverage Nanite/Instanced Meshes for draw calls, keep shaders green in Shader Complexity mode, and always use Soft References for asset loading to avoid memory bloat. Keep it simple, use built-in tools, and profile often!
Don't guess; measure. Unreal has incredible built-in profiling tools.
stat unit: Run this console command first. It shows milliseconds spent on the Frame, Game (CPU logic), Draw (CPU preparing renders), and GPU. The highest number is your bottleneck.- Unreal Insights: The absolute gold standard for deep CPU/Memory profiling. Use this instead of the old
stat dumptools. ProfileGPU(Ctrl + Shift +,): Takes a snapshot of the current frame and tells you exactly what the GPU is spending its time calculating (e.g., Post Processing, Lighting, Base Pass).- View Modes: Frequently check
Optimization Viewmodes > Shader ComplexityandQuad Overdraw. Keep it in the green!
If your Game time is high, your game logic is dragging you down.
- Kill the Tick:
Event Tickis the enemy of performance. If a Blueprint doesn't absolutely need to update every single frame, disable its tick. - Use Timers and Event-Driven Logic: Instead of checking a condition every frame on Tick, use
SetTimerByFunctionNameto run logic at specific intervals (e.g., 0.2 seconds), or use Event Dispatchers to fire logic only when things actually change. - Beware of Hard Casts: Casting to a specific Blueprint class (e.g.,
Cast to BP_PlayerCharacter) creates a hard reference. If you cast to the player in a simple rock blueprint, loading that rock will load the entire player into memory. Use Blueprint Interfaces instead. - Nativize Heavy Math: If you are looping through hundreds of arrays or doing complex math, move it to standard C++. Blueprints are heavily virtualized and slow for raw data crunching.
- Optimize Collision / Physics:
- Use simple collision primitives (boxes, spheres) instead of complex mesh collision (
Use Complex As Simple). - Turn off
Generate Overlap Eventson static objects that don't need to trigger overlaps.
Example C++ Timer (K&R Style):
void AMyOptimizedActor::BeginPlay() {
Super::BeginPlay();
// Check every half second instead of every frame
GetWorldTimerManager().SetTimer(UpdateTimerHandle, this, &AMyOptimizedActor::UpdateState, 0.5f, true);
}
void AMyOptimizedActor::UpdateState() {
// Logic here
}
If your Draw time is high, the CPU is struggling to tell the GPU what to draw. This is usually a Draw Call issue.
- Embrace Nanite (UE5): If you are on Unreal Engine 5, use Nanite for solid, opaque static meshes. It essentially eliminates traditional draw call bottlenecks and LOD generation.
- Instanced Static Meshes (ISM / HISM): If not using Nanite, or if working with massive amounts of foliage/repeating objects, use Hierarchical Instanced Static Meshes. It groups identical meshes into a single draw call.
- Aggressive Culling: Use
Cull Distance Volumesso the engine stops thinking about small objects when the player is far away. - Merge Actors: Use the Developer Tools -> Merge Actors tool to combine multiple static meshes into a single mesh to reduce draw calls in highly detailed, static areas.
If your GPU time is high, you are pushing too many pixels or doing too much lighting/shader math.
- Translucency is Expensive: Overlapping translucent materials (like smoke, glass, water) cause massive overdraw. Keep translucent areas small or use masked materials where possible.
- Simplify Materials: Use fewer texture samples. Pack your roughness, metallic, and ambient occlusion into a single texture map (RGB channels) to save memory and texture lookups.
- Lumen Scalability: Lumen is gorgeous but heavy. Ensure you are using Hardware Raytracing if available, but provide scalability settings so players on lower-end rigs can drop to Screen Space Global Illumination (SSGI) or baked lighting.
- Shadow Casting: Turn off
Cast Shadowon small scatter meshes (grass, small rocks, debris). Millions of tiny shadows will nuke your GPU.
Stutters and hitches usually happen when the engine is aggressively loading assets or garbage collecting.
- Soft References: Use
Soft Object ReferencesorSoft Class Referencesfor assets that aren't immediately needed (like inventory items, heavy UI textures, or next-level boss actors). Load them asynchronously only when required. - Texture Streaming: Ensure your textures have MipMaps enabled (power of 2 resolutions like 512, 1024, 2048). Unreal's texture streamer will automatically load lower-res versions if the camera is far away, saving VRAM.
- Garbage Collection Tuning: If you experience a stutter every 60 seconds, it's likely Garbage Collection. You can tweak GC settings in
Project Settings -> Engine -> Garbage Collectionto run more efficiently or cluster objects.
When you need to hand off optimization work to a workhorse model (like Claude 3.5 Sonnet or Gemini 1.5 Pro), use this structured subtask breakdown. Provide the AI only with the specific Blueprint/C++ code or stat logs relevant to the task.
-
Task 1: CPU Profiling & Tick Eradication
-
Context for AI: Provide the C++ header/cpp files or Blueprint text logs of actors currently using
Tick. -
Prompt: "Refactor this Unreal Engine class to remove the
Tickfunction. Replace the logic with an event-driven architecture using Unreal'sFTimerManageror Multicast Delegates. Use K&R bracket styling." -
Task 2: Hard Reference Decoupling
-
Context for AI: Provide the class that is casting heavily.
-
Prompt: "This class has a hard cast to
BP_MainCharacter. Generate an Unreal C++ Interface (UInterface) that handles the required communication, and refactor this class to useExecute_interface calls instead of casting." -
Task 3: Asset Loading Modernization
-
Context for AI: Provide the UI or Inventory class loading heavy assets.
-
Prompt: "Refactor this class to use
TSoftObjectPtr<UTexture2D>instead of raw pointers. Write the asynchronous loading implementation usingFStreamableManagerto prevent frame hitching." -
Task 4: Material Packing Scripting
-
Context for AI: Provide standard Python/Editor Utility script context.
-
Prompt: "Write an Unreal Python script that batch-finds textures suffixed with
_R,_M, and_AOin a selected folder and uses standard Unreal APIs to pack them into a single ORM (Occlusion/Roughness/Metallic) texture asset."