65+ Tips: How to improve a Unity Game's Performance
November 28, 2023
Is your Unity project feeling sluggish? Are you trying to optimize your game’s performance?
We’ve compiled a comprehensive list of Unity performance optimization tips to help you improve your game.
From utilizing the Profiler effectively to mastering texture management, these strategies will ensure your game runs smoothly on any platform.
Profiler and Debugging
- Use the Profiler.
- Profile on your target device.
- Don’t optimize code unless you confirm it’s an issue with the profiler.
- If you see Gfx.WaitForCommands in the Profiler, you are CPU-bound.
- If you see Gfx.WaitForPresent in the Profiler, you are GPU-bound.
Physics Optimization
- Avoid empty OnCollision and OnTrigger callbacks.
- Use NonAlloc physics queries.
- Use the Physics Layer Mask matrix to simplify your Physics scene.
- Avoid Mesh Colliders.
- Avoid destroying or moving static objects.
- Use the Static flag to signal static objects.
- Combine simple meshes to reduce object counts.
- Split complex meshes to enable occlusion and frustum culling.
Resource Management
- Cache GameObject and Component references.
- Reuse materials whenever possible.
- Reuse textures whenever possible.
- Use texture atlases or virtual texturing.
- Reduce your texture resolution. Reduce it again.
- Never disable mipmaps.
- Use LODs.
- Use imposters.
- Use Scriptable Objects whenever possible. They help you avoid duplicating data.
- Use object pooling.
- Use high compression for textures.
- Use power of 2 resolution for textures.
- Pre-allocate and reuse arrays and lists when possible.
- Compress your audio.
Graphics and Rendering
- Use vertex lighting for secondary light sources.
- Use simpler shaders. Avoid complex calculations. Approximate everything.
- Avoid real-time lighting and shadows. Bake your lighting, bake your shadows.
- Set your near clip as far as possible.
- Set your far clip as near as possible.
- Set your camera Field of View as narrow as possible.
- Use Dynamic Resolution Scaling.
- Avoid transparent materials.
- Avoid alpha clip materials.
- Reduce your poly count. Reduce it again.
UI Optimization
- Split up your UI Canvases.
- Make sure all UI Elements on each Canvas share the same Z value, materials, and textures.
- Avoid Graphic Raycasters.
- Disable Raycast Target.
- Avoid grid views in your UI.
- Avoid large lists of UI elements.
- Avoid overdraw for UI elements.
- Avoid layout groups.
- Disable UI objects before re-parenting them. (e.g., when Object Pooling).
- Disable Camera rendering when a fullscreen UI is up.
Code Efficiency
- Use Coroutines to process loads over multiple frames.
- Use Burst compiler to run native code.
- Use Events to avoid continuous Update() checks and calculations.
- Avoid unnecessary string creation or manipulation.
- Cache and reuse WaitForSeconds objects - new WaitForSeconds() generates garbage.
- Avoid LINQ expressions.
- Avoid RegEx.
- Trigger Garbage Collection at opportune times using System.GC.Collect.
- Use Incremental GC if you’re struggling with significant GC issues.
- Avoid running code every frame.
- Avoid heavy logic in Start, Awake, and OnEnable. Consider Lazy Loading.
- Debug.Log statements are included in Builds. Disable them before shipping.
- Use Hash IDs instead of String values for Animator, Material, and Shader properties.
- Avoid adding components at runtime. Instantiating a prefab with the component on it is typically faster.
General Optimization
- Disable any unused GameObjects.
- FPS shows average frame time, but your players feel the worst individual frame, so you should aim for consistently high FPS.
- Use Layers for Raycasts and UI.
- Set a specific time budget for each frame. Common targets are 33.33ms (30fps), 16.66ms (60fps), and 8.33ms (120fps). Track your FPS from code, then issue warnings when you dip below your target.