On an Android mid-range device, GPU Profiler shows 18 ms per frame against a target of 16.6 ms — the game cannot hold 60 FPS. A combination of 340 draw calls, overdraw-heavy effects, and 2048×2048 textures that on screen occupy 64×64 pixels — each factor individually tolerable, together a disaster.
Why comprehensive mobile game graphics optimization requires a comprehensive approach?
Mobile GPUs are tile-based: they split a frame into tiles and render sequentially. This makes them sensitive to overdraw and fill rate. Unlike desktop immediate mode GPUs that forgive more, on mobile every extra draw call or pixel shader hits performance. We combine profiling, texture compression, batching and shader tuning into a single process — otherwise there's no result.
How to measure and reduce draw calls?
A Draw Call is a CPU command to render a group of triangles with specific settings. Each draw call requires CPU-GPU synchronization and data transfer. On mobile tile-based GPUs (PowerVR, Mali, Adreno) it's more expensive than on desktop immediate mode GPUs.
Tools: Unity Profiler (GPU Usage), Frame Debugger, and for deep analysis RenderDoc on Android or Xcode Instruments on iOS. GPU Profiler right inside the editor shows batch count and SetPass calls. A good target for mobile projects is under 100 draw calls per frame, realistic for mid-core is 150–200.
Main sources of extra draw calls:
- Static Batching combines static objects with the same material into one mesh at scene start. Condition: objects must be marked Static in Inspector and use the same Material asset — identical settings but different Material Instance doesn't work.
- GPU Instancing scales better with many copies of the same object (trees, rocks, enemies of one type). Dynamic Batching works automatically for small objects (under 900 vertices), but in practice it's disabled in favor of Instancing. Unity batching techniques are essential for reducing draw calls.
- Canvas Overlay mode in uGUI: Canvas in Screen Space - Overlay renders on top of everything, and any change in any UI element marks the entire Canvas Dirty, recalculates mesh and creates a separate draw call. For UI with animated elements, always separate static and dynamic elements into different Canvases.
How do textures affect mobile game performance?
Mobile devices use Unified Memory Architecture: GPU and CPU share the same memory. 512 MB RAM is common on budget Android devices. An uncompressed RGBA32 2048×2048 texture = 16 MB. 10 such textures on a level = 160 MB just for textures.
Hardware-supported compression formats
| Format | Bits per pixel | Support |
|---|---|---|
| ETC2 without alpha | 4 bpp | Android, iOS (via ASTC?) |
| ETC2 with alpha | 8 bpp | Android |
| ASTC 4×4 | 8 bpp | iOS, Android (Adreno 400+, Mali G7x+) |
| ASTC 6×6 | 3.5 bpp | iOS, Android (newer) |
| ASTC 8×8 | 2 bpp | iOS, Android (high compression) |
| DXT5 (BC3) | 8 bpp | PC |
ASTC is the best choice for iOS and modern Android (Adreno 400+ series, Mali G7x and above). On old Android devices with OpenGL ES 2.0, ASTC is not supported — you need ETC2 fallback. Unity allows different formats per platform via Texture Importer.
Mipmaps are mandatory for 3D objects, not needed for UI. Mipmaps add 33% size in memory, but for UI elements that always render at native resolution, it's a waste. Check via Texture Importer → Generate Mipmaps → disable for all UI sprites.
Real-world case: solving OOM on mobile devices
In one project — a mobile 3D strategy — the game crashed with OOM on 512 MB RAM devices when starting a campaign. Memory Profiler showed 380 MB just for textures. Audit revealed: 60% of texture budget was taken by terrain and environment textures in RGBA32 format without compression (the developer turned off compression during prototyping and forgot to revert), another 15% — UI textures with mipmaps enabled. Solution: convert all terrain/environment to ASTC 6×6, UI to ASTC 8×8 without mipmaps, for effects with alpha — ASTC 4×4. Result: 142 MB. OOM crashes stopped, 240 MB freed for gameplay logic and audio.Why is overdraw especially critical on mobile GPUs?
Overdraw is rendering the same pixel multiple times. Semi-transparent particles, complex post-processing effects, overlapping UI elements — all contribute to overdraw. On tile-based mobile GPUs overdraw is especially expensive: every time a tile buffer is read and written again, it's extra work.
Visualize overdraw in Unity: Scene View → Render Mode → Overdraw. White areas indicate problems. Pay special attention to particle systems — particles often render dozens of semi-transparent quads on top of each other at the same point.
For particle systems: limit Max Particles, use opaque or cutout shaders where visually acceptable (cutout is more expensive in fill rate but cheaper in overdraw depth), sort particles by Sorting Layer to minimize overlap with geometry.
For shaders: simple Unlit shaders are 3–5 times cheaper than Lit on mobile devices. For background decorations, ground shadows, billboard objects, Unlit is sufficient. Lit shader with per-pixel lighting only for close-up and key objects.
What tools to use for profiling?
Start with Unity Profiler connected to a device via USB (Build → Development Build + Autoconnect Profiler). GPU Usage Profiler shows render time by category. Frame Debugger gives a detailed breakdown of draw calls. Memory Profiler provides a memory snapshot by category.
For Android additionally: Android GPU Inspector (AGI) for Adreno devices, Mali Performance Counters for Mali GPUs. They show fill rate utilization, texture bandwidth and cache hit rate — metrics not available in Unity Profiler. Check ASTC support on a device via SystemInfo.SupportsTextureFormat(TextureFormat.ASTC_6x6).
Step-by-step optimization process for FPS optimization:
- Profile with Unity Profiler and Frame Debugger to identify bottlenecks.
- Analyze draw calls: apply static batching and GPU instancing.
- Optimize textures: compress with ASTC/ETC2, disable mipmaps on UI.
- Reduce overdraw: limit particles, use opaque shaders.
- Tune shaders: prefer Unlit over Lit where possible.
- Test on target device; repeat if needed.
| Task | Duration | Cost (approx.) |
|---|---|---|
| Performance audit + report with recommendations | 2–5 days | $500–$1000 |
| Texture and material optimization (single scene) | 3–7 days | $1000–$2000 |
| Comprehensive graphics optimization (full project) | 2–6 weeks | $3000–$8000 |
| Optimization for a specific minimum device | 1–3 weeks | $2000–$4000 |
What’s included in our optimization work (deliverables):
- Detailed performance audit with full report and recommendations
- Texture recompression with optimal format selection per platform
- Batching, instancing, and shader configuration
- Profiling and elimination of bottlenecks (draw calls, overdraw, memory)
- Documentation of changes and access to optimized project files
- Training session for the client's team on best practices
- Result guarantee: FPS and stability on target devices
We have over 5 years of experience optimizing mobile games and have completed 20+ projects on Unity and Unreal Engine. Contact us for an audit of your project. Order optimization and get stable FPS on target devices.
Android Developers: ASTC texture compression - developer.android.com/games/optimize/astc





