Optimising FPS in an Unreal engine based Digital Twin simulation

Madara Premawardhana
4 min readDec 11, 2024

--

It’s a battle between your DT’s graphics and functionality! Like Kotal Khan vs Kotal Khan

Digital Twin simulations provide a critical interface for understanding, analysing, and interacting with real-world systems virtually. But, ensuring these simulations run smoothly requires careful attention to performance, particularly frame-per-second (FPS) optimization. Unreal Engine offers a robust set of tools and methods to optimize FPS. This guide dives deeper into practical methods and strategies for improving performance in such simulations. (do feel free to try out but always keep a copy of your project if you are changing project settings — or push your changes to main and do the changes in a different branch if you are using version control)

One more thing, if you’re building a Digital Twin with Unreal Engine, you may have chosen it because of all the inbuilt features that makes life easier. Remeber your Digital Twin must function before all the visualisations (so choose your priorities wisely ;) )

Look into what causes bottlenecks

The first step in optimization is to understand what is causing low FPS.

Use Unreal Engine Profiler:

  • Open the Profiler through Window > Developer Tools > Session Frontend.
  • Analyze CPU, GPU, and memory usage in real-time to identify spikes or performance issues.

Stat Commands:

  • Use commands like stat unit to view frame time for CPU and GPU and stat fps for real-time FPS feedback.
  • stat scenerendering helps identify rendering inefficiencies such as overdraw.

GPU Visualizer:

  • Press Ctrl+Shift+Comma in Play mode to bring up the GPU Visualizer. This shows GPU-related performance issues like heavy materials or shadowing

Too many traingles?

Look into your Geometry and Level Design. fficient level design is crucial for reducing computational overhead.

Implement Level of Detail (LOD):

  • Open the Static Mesh Editor for assets, and under Details, configure LOD settings.
  • Use Unreal’s built-in LOD generator (LOD Auto Generation) to simplify meshes based on distance.

Culling:

  • Enable Distance Culling via the Cull Distance Volume actor in the level to specify cull distances for objects.
  • Use Occlusion Culling by enabling it in Project Settings > Rendering > Occlusion Culling.

Mesh Instancing:

  • Use Hierarchical Instanced Static Mesh Components to batch similar meshes into a single draw call. Add instances via Blueprints or code.

Too many shaders to compile?

Simplify materials and textures in your level. Complex materials and oversized textures are a common performance drain.

Reduce Material Complexity:

  • Open the Material Editor and check the complexity using the Shader Complexity View (Lit > Optimization View Modes > Shader Complexity).
  • Replace dynamic calculations with static/precomputed values (e.g., baked normal maps).

Compress and Resize Textures:

  • Open textures in the Texture Editor and use Mip Gen Settings to ensure Unreal auto-generates mipmaps for scaling.
  • Adjust resolution via Max In-Game Size to reduce the load on the GPU.

Texture Packing:

  • Combine maps like roughness, metallic, and ambient occlusion into a single texture using channels (R, G, B, A). Tools like Photoshop or Substance Painter can aid this process.

Lights Lights!

Lighting and shadows are computationally expensive, especially in large-scale Digital Twin environments.

Static Lighting:

  • Use Static Lights for non-dynamic objects. Bake lighting into lightmaps using Build > Lighting Only in the editor.

Shadow Adjustments:

  • Reduce shadow resolution via the Directional Light Settings (Shadow Resolution Scale) and limit shadow cascades using Num Dynamic Shadow Cascades.
  • Disable shadows for small, non-critical objects by unchecking Cast Shadows in their properties.

Reflection Optimization:

  • Replace dynamic reflections with Box Reflection Capture and Sphere Reflection Capture actors.

Your code/blueprint

Blueprints and scripts can be a hidden source of performance issues.

Event-Driven Programming:

  • Replace Tick functions with custom events or timers where possible to avoid per-frame execution.
  • Use the Event Driven Loader to load only essential assets at runtime.

Code Profiling:

  • Use Unreal Insights to profile custom logic, pinpoint slow functions, and optimize scripts.
  • Avoid deep, nested loops and heavy runtime calculations.

Adjust Engine Scalability and Render Settings

Fine-tuning Unreal Engine’s scalability and render settings can have a significant impact.

Scalability Settings:

  • Adjust under Settings > Engine Scalability Settings. Prioritize reducing View Distance, Shadows, and Effects quality.

Dynamic Resolution:

  • Enable Dynamic Resolution in Project Settings > Engine > Rendering. Unreal will dynamically adjust the screen resolution to maintain target FPS.

Frame Rate Capping:

  • Set frame rate limits in Project Settings > General Settings > Framerate. A stable cap prevents unnecessary GPU load.

Multithreading and Async Processing

Digital Twins often require processing large datasets, making it essential to utilize multithreading.

Asynchronous Asset Loading:

  • Use Async Loading Screen plugin to load heavy assets without freezing gameplay.

Physics Threading:

  • Enable Use Multiple Threads for Physics in Project Settings > Physics to offload collision calculations.

Test on Target Hardware

Simulated performance on a high-end development machine often doesn’t match the real-world hardware used for deployment.

Unreal Insights:

  • Use this tool to measure performance on target devices, accessible under Window > Developer Tools > Unreal Insights.

Hardware Benchmarks:

  • Test across various GPUs and CPUs using third-party benchmarks to align performance settings with hardware capabilities.

--

--

Madara Premawardhana
Madara Premawardhana

Written by Madara Premawardhana

PhD Student at the University of Buckingham, School of Computing

No responses yet