Optimization Handbook (Ongoing)

UPDATE:

So, what I have learned is that anytime the camera is NOT looking at an object and/or that object does not currently inhabit the available screenspace, Unreal automatically (GRAPHICALLY) culls those objects.

HOWEVER

Those objects continue to transmit data collected and processed by the BASE PASS.

Now, the BASE PASS has been a real illusive thing for me to figure out because it is so all-encompassing. No one really explains what it is in lay terms because… it’s kind of everything, but nothing in specific.

I think of it as the NERVOUS SYSTEM, where, it coordinates and processes everything else, but doesn’t actually do any of the physical work.

That said, I found that pointing the camera away from a busy scene only affected GRAPHICAL components, but the BASE PASS was still very bloated.

What I’ve done to deflate it is:

  1. Shadows are not a bad thing… as long as they do not move. If you have an asset that utilizes many shadows AND moves, you need to disable as many of those shadows as possible. The shadows are not expensive; their mobility is.

  2. Hiding meshes actually does work. But only VERY little if it is static or not full of millions of triangles. If it moves, hiding it saves TONS of GPU. You can hide objects via:
    -Cull Distance Volume
    -Packed Level Actor (ONE OF MY FAVORITE TOOLS)
    -Setting Visibility
    -Setting Hidden-In-Game
    -Setting Min/Max Draw Distances (Must be in GAME MODE VIEW “G” to witness)
    But again, you only really see the difference for MOVING objects.

  3. I created “IMPOSTERS” by taking very large actors, and converting them into (Packed Level Actors ->) Merged Meshes. Then I ran them through a SIMPLIFICATION process in the MODELER. These “IMPOSTERS” can act as persistent large actors in a level, so while the TRUE mesh is hidden (like a building or other structure), the Imposter, at a much lower resolution and triangle count takes its place.

  4. Draw calls are overrated in their concern. Yes, keep them as low as you can, but unless you have over 5,000, you’re not really going to have it be your main concern. Your main concern are objects that move or have material functions that simulate movement (like foliage). Windy foliage + Shadows = VERY affected FPS/MS.

  5. Check your lights! Make sure your attenuation distances are not too high, as Unreal will use calculating power to simulate the effects of the light, even if you can’t actually see it make a difference!

(Amended: 2/25/2024)

-What a difference a month makes! Anyway:

  1. LODs are still the way to go, even with Nanite enabled. They work together. Make sure that screen-spaces are properly adjusted, especially for larger/more complex objects. Default screen-spaces are VERY under-optimized. (Often requiring the camera to be VERY far away before seeing results. It is HIGHLY recommended you edit these screen-spaces yourself.)

(Amended: 3/4/2024)

  1. Nanite is amazing, but only for HUGE objects, HUGE worlds, or for large numbers of objects that are spread out LONG DISTANCES. Nanite is (at the moment) an OPEN WORLD functionality. If you’re working with a dense area, you MUST use CULLING and LODs (assuming these objects are already low-poly.)

(Amended: 3/7/2024)

  1. Serialization (event-driven processes) are more performant than ticks. However, if you do use ticks, make sure that they aren’t ticking ON EVERY FRAME (if they do not have to.) You can create your own ticks. I have ticks that pulse once every 60-120 frames.

  2. Draw Counts are not always called! That means, you could have some areas with 10,000 draws and some with only 1,000. In cases where these counts are high, you need to CULL/HIDE unnecessary nearby meshes. You can utilized PACKED LEVEL ACTORS to facilitate this.

  3. When editing LODs, again, they are usually not optimized. So, it is important to edit the PERCENT TRIANGLES to lower values for farther distances. You’d be surprised how many vertices and triangles a simple vase could have in scene!

(Amended 4/20/2024)

  1. Make sure that your lights are STATIC not STATIONARY or MOVABLE, unless absolutely necessary! Otherwise, their affect on the environment is going to constantly be calculated during runtime. (This is only applicable to non-Lumen lighting. Otherwise, stick to movable or stationary.)

(Amended 5/26/2024)

  1. COLLISIONS. I don’t know how many times I’ve seen a simple object have needlessly complex collision. Go through your assets and see if you can simplify their collisions to basic shapes. This is especially critical if the actor is moving. The less your CPU has to compute, the better.

  2. Texture Sizes are not super important as Unreal will automatically compress them to hit a certain performance goal. If, however, you want more control over what Unreal compresses (for example, you do NOT want Unreal to compress facial meshes, but rocks are just fine), then you can edit the Max resolution of individual textures. This is best done with the MATRIX tool.

  3. LEVEL STREAMING. Learn it. Every time you add a new asset, it is cached for quick retrieval from the GPU. So, even if you hide it, it’s taking up VRAM (much less than if it’s visible, but this can add up over time). My FPS speeds for my dense open-world went from 60 → 70 FPS (originally maxed out at 30 FPS before I started optimizing)!!! And I only unloaded a handful of actors.

(Amended: 8/12/2024)

  1. Overdraw can GREATLY increase GPU usage. For those who do not know, a simplified explanation of Overdraw is when the GPU renders a pixel more than it needs to. So, if you have transparent or semi-transparent objects in your scene, those objects need to be drawn multiple times to sell the illusion of transparency. This issue is especially egregious in particle systems. So, make sure your particle systems are using LODs, and try to avoid large, (semi)-transparent filters/post processes/materials. You can check the Overdraw of your level here:

  1. Blueprints are ticking actors with built-in functionality. As such, having many Blueprints in your scene can slow it down. If you are using Blueprints for simple functions like VISIBILITY, SHADOWS, or COLLISION, you can utilize Actor Tagging instead. Add a tag to an actor, name it, then call the tag in a master blueprint.

  2. TEXTURES. I mean it. Limit the amount of textures that are loaded at any given time in your scene. You would be surprised that a single mesh can have dozens of textures. Be wary of content purchased on the Marketplace, because, although an asset can be beautiful, they are generally created by artists disinterested in their use in gaming situations. You can SIMPLIFY meshes after deleting or reducing the unique amount of textures.

An example:

I had a background actor that originally had 260+ textures…

I duplicated every texture that I could, so instead of having 120 unique textures, I now have 18 or so (i.e. T_Wood_01, T_Wood_02, T_Wood_03 would be replaced by a general wood texture that looks similar to the three).

Then I MERGED the edited mesh and got this:

Now instead of 260+ textures being calculated and rendered, only 18 are, and no visual fidelity is lost.

  1. And while we’re on simplification, make sure (ONLY AFTER YOU ARE COMPLETELY SATISFIED WITH THE WORLD) that you don’t have more static meshes than you need. You can simplify a bunch of buildings with hundreds of modular meshes into one static mesh that will reduce individual calls, using the method above.

(Amended: 10/28/2024)

  1. Garbage Collection. Unreal does a pretty good job at this but keep in mind that anytime you CREATE an asset (like a Level Sequence Player or UI Element), if you are using code that loops, duplicates of these assets will pile up, and their management could affect overall performance. Make sure if you do have looping code to: a) save a reference and use that reference upon any iterations or b) delete the asset once the function has completed with the Destroy Actor node. I didn’t realize how bloated the number of actors was becoming in my scene because of this.

I’ll add more as I continue optimizing.

I’m finding, more and more, how incomplete “official” optimization tutorials truly are.

2 Likes