On the internet, I often see a lot of misinformation about optimization, or people using Unreal Engine tools in the most unoptimized ways possible. This includes, but is not limited to; creating individual materials for every texture, using inefficient file formats for textures, assigning complex collision to meshes where it's not needed, running CPU calculations on thousands of particles just to create puddle splash effects, and focusing way too much on triangle counts (this one especially came up a lot during my teaching sessions), using particles where a material shader could get the job done, and so on.
I’ll try to dive into every major topic; from baking lights to creating efficient materials, reducing draw calls, and identifying what overloads your CPU, in the simplest way possible. That said, you should be aware that every project will have its own needs, and the "sacrifices" you need to make will depend on the genre and how your game is structured. This will be quite an extensive guide, so I’ll break it into different parts. At the end of each post, you’ll find links to the previous and next tutorials. Now that we’ve got that out of the way, let’s begin the tutorial.
Almost everything in your game contributes to a "draw call."
What the hell is a "draw call," then?
A "draw call" is basically when the CPU "calls" the GPU and says, "Hey, we have this mesh here. You need to draw (render) it." And the GPU goes, "Alright, I'll do it." Even though modern GPUs can render LOTS of polygons, when CPUs need to make/organize a lot of "calls" (preparing many draw calls to tell the GPU to render something) per frame, it can saturate the CPU and cause a performance hit. This is the main reason why we need to keep our draw calls at a reasonable level.
When it comes to drawing (rendering) calls, the heavy work is handled by the GPU. The CPU’s role is mostly to make the “call” to the GPU. Most of the time, unoptimized scenes will cause overhead on the GPU since it's doing the heavy lifting (rendering). However, it's important to remember that the CPU still plays a crucial role in the process, and its resources are also used. More complex materials, shaders, high-resolution textures, post-processing effects, etc., mean more work for the GPU.
The CPU is more concerned with collisions. It constantly checks for collision overlaps, handling responses such as: "Did it trigger? Did it bounce? Did it block?". More collisions to check = more overhead on the CPU. The more complex the collision gets = the more overhead on the CPU.
If you're wondering which has more impact on performance: draw calls or collisions: the answer is a bit of both. For static objects, high draw calls might matter more. For dynamic or interactive objects, complex collision is usually more damaging. A single merged mesh with complex collision can wreck performance far worse than a dozen simple meshes with more draw calls.
Collision is expensive. Complex collision is even more expensive. Remove collision from objects the player can't interact with. A good example would be small items like books, lamps, keys, or pens placed on a table or sofa. If the player can't interact with them and won't collide with them, remove their collision entirely. For objects the player can collide with, delete the default collision generated by Unreal and add a simple box (or capsule) collision instead. Only use complex collision when absolutely necessary; such as in traversal areas or objects with intricate creases, bumps, or shapes.
Your biggest direct enemy isn’t triangle count. It still matters, but here’s the truth: modern hardware can handle far more triangles than you’ll typically need. The real performance bottleneck, especially in modern engines, is lighting complexity and shadows. Think dynamic lights, overlapping lights, reflections, volumetrics; basically anything that’s calculated in real time. All of this puts a heavy load on the GPU. Triangle count affects how many vertices need to be processed, but it doesn’t scale with screen resolution (which is good) the way lighting does. Then there’s your shaders. Complex materials; like subsurface scattering, dynamic global illumination, and especially translucent materials are GPU-intensive. Most modern engines use deferred rendering, which separates lighting from geometry. That allows you to push more triangles, but lighting still dominates the cost. Lighting affects all objects, no matter their poly count. Even low-poly meshes can be expensive if they’re lit by multiple dynamic lights with shadows. Then come post-processing effects, and after that, draw calls and object counts. Triangle count becomes more of a factor if you have tons of unique objects (which increases draw calls and physics complexity if collisions are enabled), or if you're targeting mobile platforms. None of this means you should stop optimizing your assets or ignore LODs; but triangle count usually isn’t the most critical issue to tackle first.
Above, we mentioned that modern hardware (even low-end systems) can handle a lot of draw calls, but it’s super easy to go overboard. (But again; excessive numbers still hurt performance, especially on lower-end systems or mobile platforms.) If you have a bunch of stuff lying on a bed, merge everything into a single mesh using the "Static Mesh Merge Tool" in Unreal. Be aware that when multiple static meshes are merged into one, each of the original objects retains its respective collision. You'll need to remove the collisions from the merged mesh and add a simplified one instead. More collisions to calculate = bigger impact on performance.
If you've been reading about optimization in Unreal Engine 5, you might have come across the terms "per-poly" and "simple convex collision." But what do they actually mean?
Now, here's a question for you:
In almost all cases, using multiple simple box collisions is significantly cheaper than relying on a single complex (per-poly) collision. Complex collisions place a substantial load on the CPU and are almost never used at runtime. For performance-critical objects; especially if they’re interactable or movable; use multiple simple box or convex collisions instead. Avoid complex collision whenever possible. Instead of placing multiple basic shapes, you can alternatively double-click the asset, go to Collision > Auto Convex Collision, and make the necessary adjustments in the bottom-right corner. This allows you to create a simple yet detailed collision, and it’s still more performance-friendly than using complex collision.
If you manually add three box collisions to a mesh, Unreal Engine will treat them as three separate simple collision shapes; not one unified shape. While it still counts as “Simple Collision,” using multiple collision primitives adds a small amount of processing overhead compared to using a single box. However, it’s still far cheaper than using per-poly (complex) collision. Wherever possible, try to use a single simple collision shape for the entire object. That said, if the shape is complex and requires multiple boxes, using multiple simple boxes collision is still the recommended approach rather than using the complex collision.
The best approach is still to use multiple simple collision shapes; such as boxes, capsules, or convex hulls to build out the shape of the cave interior. Just to underline: complex collision is very CPU-intensive and can cause issues with dynamic physics objects, line traces, or AI navigation. Another solid option is to render only the cave asset while overlaying the walkable areas with custom blocking volumes or collision-only meshes that aren't rendered. Always test with the player controller, AI navigation, and physics objects to ensure that both performance and collision behavior are acceptable.
There are other cases where complex collision can be useful, but in game development, it allows developers to “Use Complex Collision as Simple” and quickly move on with prototyping. It lets artists or level designers get assets into the game without needing to create custom collision meshes right away.
Want to finish this tutorial?
Support my work and access the full tutorial + bonus content by becoming a Patron!