Skip to content

Instantly share code, notes, and snippets.

@drawcode
Last active June 12, 2026 20:19
Show Gist options
  • Select an option

  • Save drawcode/57a58dddf2ad2fdbf8c79b042d564649 to your computer and use it in GitHub Desktop.

Select an option

Save drawcode/57a58dddf2ad2fdbf8c79b042d564649 to your computer and use it in GitHub Desktop.
skill-unreal-performance-checklist.md
title Unreal Engine Performance Guidelines
author CodeGameDevCommon
type skill-file
tags
unreal-engine
performance
optimization
cpu
gpu
profiling
best-practices
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!


1. 🕵️ Identifying the Bottleneck

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 dump tools.
  • 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 Complexity and Quad Overdraw. Keep it in the green!

2. 🧠 Game Thread Bound (CPU / Blueprint / C++)

If your Game time is high, your game logic is dragging you down.

  • Kill the Tick: Event Tick is 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 SetTimerByFunctionName to 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 Events on 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
}

3. 🎨 Draw Thread Bound (CPU Render Prep)

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 Volumes so 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.

4. 🖼️ GPU Bound (Rendering / Shaders)

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 Shadow on small scatter meshes (grass, small rocks, debris). Millions of tiny shadows will nuke your GPU.

5. 💾 Memory & Asset Loading Bound

Stutters and hitches usually happen when the engine is aggressively loading assets or garbage collecting.

  • Soft References: Use Soft Object References or Soft Class References for 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 Collection to run more efficiently or cluster objects.

🛠️ Optimization Subtask Plan (For AI Workhorses)

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 Tick function. Replace the logic with an event-driven architecture using Unreal's FTimerManager or 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 use Execute_ 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 using FStreamableManager to 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 _AO in a selected folder and uses standard Unreal APIs to pack them into a single ORM (Occlusion/Roughness/Metallic) texture asset."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment