Skip to content

GuardianOfGods/unity-mobile-optimization

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 

Repository files navigation

unity-mobile-optimization

banner

👋 Hi there, I'm HoangVanThu. This repository discusses various ways to optimize your games on mobile devices, helping enhance overall performance. These techniques aim to improve the gaming experience by optimizing resource usage and performance on mobile platforms.

The article has been synthesized from various sources on the internet. If you find any inaccuracies or have any questions about the content, please submit an issue or provide direct feedback to me.


Table of Contents


Reduce Build Size

Texture

Texture import settings on Inspector

  • Most of your memory will likely go to textures, so the import settings here are critical. In general, try to follow these guidelines:
    • Lower the Max Size: Use the minimum settings that produce visually acceptable results. This is non-destructive and can quickly reduce your texture memory.
    • Use powers of two (POT): Unity requires POT texture dimensions for mobile texture compression formats (PVRCT or ETC).
    • Atlas your textures: Placing multiple textures into a single texture can reduce draw calls and speed up rendering. Use the Unity Sprite Atlas or the third-party TexturePacker to atlas your textures.
    • Toggle off the Read/Write Enabled option: When enabled, this option creates a copy in both CPU- and GPU-addressable memory, doubling the texture’s memory footprint. In most cases, keep this disabled. If you are generating textures at runtime, enforce this via Texture2D.Apply, passing in makeNoLongerReadable set to true.
    • Disable unnecessary Mip Maps: Mip Maps are not needed for textures that remain at a consistent size on-screen, such as 2D sprites and UI graphics (leave Mip Maps enabled for 3D models that vary their distance from the camera).
    • Compress Texture: For almost every mobile device today, format should be RGBA Compressed ASTC. For older devices, you can choose ET2 or ETC compress.

Compress texture recommended

Texture compression format - Player Settings

Texture compression format in Player Settings

  • Texture compression format: Player Settings provide a global default for texture compression, affecting all textures unless overridden.
    • ETC (Default): ETC (Ericsson Texture Compression) is a common format used on Android devices.
    • ASTC: ASTC (Adaptive Scalable Texture Compression) is a modern texture compression format suitable for a variety of platforms, including newer mobile devices.

Audio

Audio import settings in Inspector

  • Alway enable Force to mono to reduce the file size, use less memory and many other advantages.
  • Reduce the size of your clips and memory usage with compression:
    • Use Vorbis for most sounds (or MP3 for sounds not intended to loop).
    • Use ADPCM for short, frequently used sounds (e.g., footsteps, gunshots). This shrinks the files compared to uncompressed PCM, but is quick to decode during playback.
  • Sound effects on mobile devices should be 22,050 Hz at most. Using lower settings usually has minimal impact on the final quality; use your own ears to judge.
  • The setting varies by clip size.
    • Small clips (< 200 kb) should Decompress on Load.
    • Medium clips (>= 200 kb) should remain Compressed in Memory.
    • Large files (background music) should be set to Streaming.

Mesh

Audio import settings in Inspector

  • Much like textures, meshes can consume excess memory if not imported carefully. To minimize meshes’ memory consumption:
    • Compress the mesh
    • Disable Read/Write
    • Disable rigs and BlendShapes
    • Disable normals and tangents

Animation

Animation import settings in Inspector

  • You can change properties such as rotation error, position error, and scale error to reduce file size.
  • Be cautious because these parameters introduce animation errors.

Optimize Performance

Scripting

Clean Code

  • Your game may have many code redundancy, so clean code could increase the performance for your game.
  • Here I found a good clean code topic.

Avoid Allocating Memory

Every time an object is created, memory is allocated.

Situation 1: In Unity, the term "string" refers to a data type, not a variable name.

  • String concatenation creates garbage.
- Debug.Log("hello" + " " + "world");
  • This code above will create 3 difference string and located in the heap memory. So this should be:
+ Debug.Log("hello world");

Situation 2: Use classes and struct wisely.

  • Structs = stack, Classes = heap
  • Structs are faster for small data
  • Classes are better for complex objects

Situation 3: Use C# Events instead of UnityEvents.

  • UnityEvent is slower and generates garbage.

Use Algorithm

  • The algorithm will significantly improve the performance of the game, apply it whenever possible.

Centralized Update

Illustrative Image

  • Imagine 100 enemies moving in the same direction at the same speed. If each enemy has its own Update method, Unity must call the same logic 100 times every frame, creating unnecessary overhead. By using a single centralized update to move all enemies together, the engine work is reduced, performance improves, and the system scales better.
  • This approach is commonly known as a Centralized Update (or Manager-based) pattern, where multiple entities are updated through a single update loop instead of each entity having its own Update method.

Technical

Object Pooling

Example of Object Pooling

  • Because Destroy(GameObject) is expensive and generates garbage memory, frequently creating and destroying objects can cause performance spikes and GC stuttering, especially on mobile devices. Object Pooling avoids this cost by reusing existing objects instead of destroying them, resulting in more stable performance, fewer GC allocations, and smoother gameplay.

Recyclable Scroll

Recyclable scrollview

  • Avoid creating 9999 UI items, reuse them instead.

Physics Optimization

Physic update

image

Fixed time step

  • Mobile games typically target 60 FPS (frames per second) — this is the most comfortable and responsive framerate for players. Unity’s Physics system uses Fixed Timestep, which by default updates every 0.02 seconds, equivalent to 1 second / 60 frames.

  • However, when launching your game in many different markets, you will encounter a wide range of low-end devices. To optimize performance for these weaker devices, you can safely set Fixed Timestep = 0.033s, which corresponds to 30 FPS. You can also retrieve the device’s hardware specifications and dynamically adjust the FPS in your code accordingly.

Layer and Collider

image

Layer matrix

  • In Unity, all physical interactions are processed through object layers and colliders. Having too many colliders interacting unnecessarily will degrade your game’s performance. Therefore, you should optimize by organizing your layers and colliders properly.

  • If two layers do not need to interact, disable their interaction immediately in the Layer Collision Matrix so the Physics system doesn’t waste time checking them. Additionally, in newer versions of Unity, each collider can individually exclude specific layers that it should not interact with.


Tips and Tricks

Staying with Unity LTS

  • Avoid Tech Stream for stability.

Use original uncompressed WAV files as your source assets when possible.

  • Avoid double compression quality loss.

Use the minimum Audio Source you can in your game.

  • Every active Audio Source consumes CPU/RAM.

Customize Linear vs Gamma color space.

  • Gamma = 10–30% faster.

Try using incremental GC (Garbage collection)

  • Smoother GC in some cases.

Using LOD technical

  • Reduce triangles for distant meshes.

Bake Mesh

  • Reduce draw calls by combining meshes.

Fake Shadow

  • Disable real shadows → huge performance gain.

Pack texture

  • Use Sprite Atlas for batching.

Enable GPU Instancing

  • Reduce draw calls for repeated meshes.

Disable Vsync

  • Avoid FPS lock + battery drain.

Choose Suitable Graphics API

  • Use GLES2 + GLES3 for compatibility.

Others


Support

  • If you like this topic, you can give this repository a star ⭐
  • I would greatly appreciate it if you could support me with a cup of coffee