Mobile Game Performance Profiling
"The game is lagging" — that's not a diagnosis. It's lagging because the CPU can't keep up with the GPU, because GC is collecting garbage, because textures don't fit in VRAM, because the shader is too heavy for an Adreno 618, or because Metal behavior changed on iOS 17. Without a profiler it's guesswork. With one — concrete numbers and concrete culprits.
Tools and What Each Shows
Unity Profiler — the starting point. Deep Profile mode slows the game but shows all calls with allocations. Connect via Development Build + Autoconnect Profiler or USB. Always test on device, not in the editor: different GC, different render backend, different latencies on device.
Key markers in the CPU trace:
-
GC.Collect— garbage collection. If > 1 ms and occurs more than once every few seconds — allocation problem in hot path -
Camera.Render→RenderForwardOpaque.Render— main GPU load -
Physics.Processing— physics. If > 3 ms at 60 FPS budget — too many colliders or suboptimal FixedTimestep settings
Android GPU Inspector (AGI) — for Android on Qualcomm or Mali. Shows GPU time per draw call, pipeline bubbles (pauses between vertex and fragment shaders), ALU utilization. Critical for understanding what's heavy on GPU: geometry, overdraw, or fill rate.
Xcode Instruments — for iOS. Use Metal System Trace for GPU, Time Profiler for CPU, Allocations for memory. Thermal State in Instruments shows when the device starts throttling due to overheating — a common cause of unstable FPS after 5 minutes of gameplay.
Snapdragon Profiler — alternative to AGI for Adreno. Simpler for snapshot mode, shows shader efficiency well.
Typical Findings
CPU-bound Scene
Symptom: VSync waits on GPU less than 1 ms (GPU keeps up), but frame still takes 20+ ms. CPU is the bottleneck.
Most often culprit — Update() methods with heavy logic, LINQ queries in hot path (each creates allocation), or FindObjectsOfType inside Update (O(n) across all scene objects). Memory Profiler shows this as constant GC.Alloc of several KB per frame.
Solution: transition to Data-Oriented Technology Stack (DOTS/ECS) for mass objects, or minimally — cache results, replace LINQ with explicit loops, event-driven architecture instead of polling.
GPU-bound, Overdraw
Symptom: GPU time is high, but draw call count is small. AGI shows high Fragment Shader time.
Overdraw — drawing the same pixels multiple times due to transparent object overlap. In Unity, visible in Overdraw mode in Scene View. Dark red regions — drawing each pixel 4+ times. Typical for 2D games with many particle layers.
Solution: sort transparent objects, limit simultaneously active particles, replace transparent sprites with opaque where artistically possible.
Thermal Throttling
On iPhone after 3–7 minutes of intensive gameplay, processor temperature reaches threshold, and iOS lowers CPU/GPU frequency. FPS drops from 60 to 40–45 without any changed load in the game. Check via ProcessInfo.thermalState (iOS) — at .serious or .critical reduce graphics quality preventively.
Android has similar mechanism — PowerManager.getThermalHeadroom() (API 29+).
Report Format
After profiling, deliver a report with specific markers: what's slow, on which device it reproduces, how many ms it takes, and recommendations with priority. Not "optimize physics," but "FixedUpdate in EnemyAI.cs calls Physics2D.OverlapCircleAll every 20 ms with 200 active enemies — total 4.2 ms CPU, rewrite with Physics2D.OverlapCircleNonAlloc with result pool".
Timeline: audit and report — two to three business days. Implementation of fixes — separate estimate.







