How to Optimize 3D Assets for Unreal Engine
Choose import precision, Nanite or conventional LOD, materials, textures, collision, skeletal budgets, and profiling for shipping Unreal builds.
Unreal Engine can ingest dense source assets and offers systems such as Nanite, LOD groups, texture streaming, virtual textures, and detailed profilers. None removes the need to define an asset's target platforms, view, materials, collision, and memory envelope. A mesh appropriate for Nanite on desktop may need conventional LODs for another renderer or platform.
Optimize the cooked runtime asset and representative level, not only the source FBX or GLB.
Define the project path#
Record the Unreal version, target RHIs and platforms, rendering features, scalability tiers, Lumen and shadow policy, Nanite support, ray tracing, virtual texture use, and frame target.
One Unreal Unit is 1 centimeter by standard convention. Verify known dimensions and pivot behavior after import. Coordinate conversion, build scale, and nested transforms can make static appearance correct while collision and animation are wrong.
Profile a packaged Development or Test build on target hardware. Play In Editor is useful for diagnosis but carries editor overhead. At 60 Hz the complete frame deadline is 16.67 milliseconds; reserve headroom for gameplay and UI.
Choose an import pipeline deliberately#
Unreal supports FBX and the Interchange framework, including glTF and GLB paths for supported workflows. Pin one repeatable import route and its options.
The current Interchange reference exposes controls for importing LODs, collision, Nanite build, lightmap UVs, tangents, weighted normals, UV precision, degenerates, morph targets, skin-weight precision, and animation sampling. Each can change runtime data.
Store import settings in pipeline assets, scripts, or documented presets. A reimport must reproduce the same:
- scene and unit conversion;
- mesh combination policy;
- normal and tangent behavior;
- vertex color policy;
- LOD group;
- collision naming and generation;
- lightmap UV channel;
- Nanite and distance-field build settings;
- skeletal and morph thresholds;
- material and texture ownership.
Inspect the Static Mesh or Skeletal Mesh Editor after import. Review actual triangles, vertices, UV channels, materials, bounds, collision, LODs, and build warnings.
Decide whether Nanite fits#
Nanite virtualized geometry can render very high geometric detail with automatic fine-grained selection on supported paths. It is not a command to ship raw scans unchanged.
Clean source geometry first:
- remove invisible internals and capture debris;
- remove duplicates and degenerates;
- consolidate pointless material slots;
- repair visibly broken normals and UVs;
- establish scale, pivot, and component semantics;
- limit texture dimensions independently;
- build appropriate collision;
- verify platform and material support.
Nanite reduces the need for hand-authored static-mesh LODs in many cases, but disk size, streaming, build time, material cost, aggregate geometry, shadows, and memory remain. Masked, deforming, translucent, or specialized material cases need current feature verification.
Compare Nanite enabled and conventional candidates in the target scene. Use Nanite visualization modes and profile, rather than assuming the denser source is free.
Conventional LOD remains essential#
Use conventional LOD for unsupported platforms, skeletal meshes where appropriate, or assets that do not fit the Nanite path. Unreal's automatic static-mesh LOD generation uses quadric-style simplification and LOD groups can standardize project categories.
LOD thresholds use screen size rather than a universal physical distance. Generate candidate reductions, review silhouette and material behavior, then set screen thresholds. Keep origin and bounds stable.
An illustrative chain might use 100%, 45%, 18%, and 6% triangles. It is not a recommendation. A thin mechanical feature may fail at 45%; a dense rock may pass at 10%.
Use hysteresis or transition strategy supported by the project. Review shadow and reflection transitions too. A visual LOD switch can be acceptable while its shadow pops.
Geometry precision and tangents#
Import only attributes used by the material and systems. Extra UV sets, vertex colors, or morph data consume memory. Do not remove a channel without tracing its consumers.
Choose normal and tangent import or recomputation deliberately. MikkTSpace compatibility matters for tangent-space normal maps. Triangulate before baking when importer and baker might choose different diagonals.
High Precision Tangent Basis and Full Precision UV options improve precision and increase storage. Test broad glossy highlights, fine text, large-coordinate meshes, and UV seams before enabling globally.
If an asset needs precision only in one area, consider separating it rather than making every mesh use the highest format. Document settings per class.
Remove degenerates when they are accidental, but inspect count changes. A large number points to source cleanup needs.
Materials and sections#
Each material slot creates a mesh section and can create draw work per pass. A product with 40 nearly identical material slots remains expensive even when geometry virtualizes efficiently.
Canonicalize material instances and use parameters for legitimate variation. Remove unused slots. Combine small compatible regions through atlas, masks, or vertex data only when texture memory and variants remain sensible.
Material complexity matters per pixel. Use the Material Editor statistics and platform shader analysis. Layered, translucent, subsurface, clear-coat, or complex World Position Offset paths need target testing.
Count passes through frame captures. Base pass, depth, shadows, velocity, custom depth, and reflections can multiply sections. A 20-section mesh rendered through 4 relevant passes can imply around 80 submissions before culling details.
Transparent materials add sorting and overdraw. Prefer opaque or masked where visually correct. Do not enable two-sided rendering to conceal incorrect winding on solids.
Textures and streaming#
Set texture group, maximum size, compression settings, color space, mip generation, and LOD bias from semantic use and target platform.
A 4096 × 4096 RGBA8-equivalent top level has 64 MiB of uncompressed texels; a mip chain approaches 85.3 MiB before actual platform format. Cooked GPU compression changes this, but source PNG bytes are not memory.
Use texture streaming budgets and inspect wanted versus resident mips. Large hero textures can evict many smaller scene textures. Virtual Texturing can help suitable workloads but adds its own page tables, caches, feedback, and material constraints.
Normal maps, masks, HDR data, alpha cutouts, and color textures need distinct compression review. Check the actual cooked platform, not only editor preview.
Remove duplicate images and unused alpha. Pack linear masks when their resolution, UVs, and lifecycle align.
Collision is a separate representation#
Complex render geometry is rarely the best gameplay collision. Import authored simple collision through naming conventions such as UCX, UBX, USP, and UCP where the pipeline supports them, or build engine-side proxies.
Choose primitives, convex hulls, or complex collision according to interaction. Complex-as-simple can be appropriate for static queries and inappropriate for dynamic physics. Measure cooking, memory, and trace cost.
Nanite visual detail does not eliminate collision design. Navigation, line traces, physics, and placement may use different structures.
Validate gaps and contact surfaces. An over-simplified convex hull can block doorways or make a product float above a table.
Skeletal meshes#
Skeletal assets need separate budgets for vertices, bone influences, morph targets, animation, cloth, physics assets, and skinning passes.
Test extreme poses for every skeletal LOD. Preserve root skeleton compatibility and sockets. Lower LODs can reduce bones or influences through a documented mapping, but attachments and gameplay bones must survive.
Import only required morph targets. Hundreds of dense morph deltas consume memory even when inactive. Use animation compression and curve reduction against contact and facial tolerances.
Profile CPU and GPU skinning on target. Triangle reduction may not help if animation evaluation or cloth dominates. Conversely, a heavily skinned crowd multiplies vertex cost and benefits from LOD, animation budgeting, and visibility control.
Physics Assets should use deliberate bodies, not automatic complexity accepted without review.
Instance repeated meshes#
Repeated static meshes can use Instanced Static Mesh or Hierarchical Instanced Static Mesh components where behavior fits. This reduces object and submission overhead and can provide spatial hierarchy.
Instances must share mesh and compatible material state. Per-instance data has limits and material support. Do not combine objects needing independent physics, animation, or unique sections without testing.
Foliage and PCG systems can manage high instance counts, but overdraw, shadows, World Position Offset, and collision still multiply. Profile the complete population.
Actor merging or HLOD can reduce distant scene cost. Cluster spatially so bounds and streaming cells remain useful.
Lighting, shadows, and derived data#
Static meshes may generate lightmap UVs, distance fields, Nanite data, ray-tracing acceleration structures, mesh cards, and derived render resources. These add build time, disk, and memory.
Enable only systems used by the project. Adjust distance-field resolution for assets whose silhouette actually contributes. A tiny prop does not need a high-resolution field by habit.
Virtual Shadow Maps and conventional shadows have different behavior. Control caster participation, resolution policy, and LOD. Dense masked foliage can remain expensive even with Nanite.
Rebuild derived data after source changes and inspect cook size deltas. A source triangle saving can be dwarfed by an oversized lightmap or distance field.
Profile with Unreal's tools#
Start with stat unit to separate Frame, Game, Draw, GPU, RHI thread, and dynamic-resolution timing. Use stat RHI, stat SceneRendering, stat GPU, ProfileGPU, Unreal Insights, and platform GPU tools as appropriate.
The Render Resource Viewer provides a snapshot of GPU allocations with resource name, size, type, flags, and owner, including vertex/index buffers and render resources. Use filters and owner paths to attribute memory.
Unreal Insights can capture CPU/GPU timing and memory allocation traces. RenderDoc or platform tools can inspect draw and GPU state when supported.
Run controlled tests:
- disable Nanite or force a conventional LOD candidate;
- replace materials with simple opaque instances;
- reduce screen percentage;
- disable shadows or Lumen features independently;
- hide half the instances;
- stop animation and cloth;
- reduce streaming texture mips.
Match the fix to the counter that moves.
Cook and package analysis#
Editor asset size is not cooked package size. Run a target cook and analyze containers, BulkData, derived geometry, textures, shaders, and dependencies.
One material reference can pull a broad texture or function dependency set. One map can retain assets through hard references. Use Asset Audit, Size Map, Reference Viewer, and cook reports.
Test loading through the actual IoStore or packaging path. Record disk read, decompression, object creation, GPU upload, first-use shaders, and memory peak.
Keep optional high detail in separately streamable chunks where product flow supports it. Ensure fallback LOD and material exist while data streams.
Automate asset validation#
Use Editor Utility, Python, commandlets, Data Validation, or pipeline code to enforce class rules:
- scale and bounds;
- triangles, vertices, sections, and LODs;
- Nanite policy;
- UV and lightmap channels;
- collision complexity;
- texture dimensions and groups;
- material slot and shader rules;
- skeletal bones, influences, morphs, and sockets;
- derived-data settings;
- platform and cook ownership.
Exceptions need a reason, owner, and scene profile. Static checks complement packaged performance tests.
Unreal shipping checklist#
Treat scalability tiers as separate acceptance environments. A hero asset that passes the desktop Epic profile may need a conventional LOD path, smaller texture group, simpler collision, and fewer material passes on a 60 Hz console or mobile target. Record the effective console variables beside each capture so a later engine or device comparison is reproducible.
Recheck bounds after every reimport. An off-screen socket, particle helper, or malformed vertex can keep an actor visible, affect streaming decisions, and make screen-size LOD thresholds behave unexpectedly. Compare local bounds with an approved numerical range and visualize them in the level; do not wait for a crowded scene to reveal the error.
- Import route and settings reproduce on reimport.
- Scale, pivots, transforms, and bounds match references.
- Nanite eligibility and target support are verified.
- Conventional LODs use tested screen-size thresholds where required.
- Normal, tangent, and UV precision follow material evidence.
- Sections and material passes are intentionally bounded.
- Cooked texture formats and streaming behavior fit memory.
- Collision is purpose-built rather than inherited from visual density.
- Skeletal LODs preserve poses, sockets, morph needs, and physics.
- Instancing, HLOD, and streaming keep useful spatial grouping.
- Render Resource Viewer, Insights, and GPU captures validate the target scene.
- Cook reports show package and dependency costs, not editor guesses.
Sources and further reading#
- Unreal Engine: Interchange Import Reference
- Unreal Engine: Static Mesh Automatic LOD Generation
- Unreal Engine: Render Resource Viewer
- Unreal Engine: Unreal Insights
- Unreal Engine: Stat Commands
Unreal optimization is a cooked-content and frame-systems problem. Import deliberately, choose Nanite or conventional LOD by target evidence, control materials, textures, collision, and derived data, and use engine profilers to find the actual limiting resource.