Home / Blog / Unity Mobile Optimization: WebGL to Android Performance

Unity Mobile Optimization: WebGL to Android Performance

WebGL ran smoothly at 60fps. Android was a slideshow at 12fps. Here's how we fixed it.

The Mobile Performance Gap

The Ascendant Continuum is being developed for WebGL first—targeting 60fps on desktop and smooth 30fps on modern phones via browser. When we compiled our early prototype to native Android expecting better performance, we encountered challenges: 12fps on flagship phones, crashes on mid-range devices, 8-second load times, and thermal throttling after 3 minutes. The culprits: excessive overdraw from layered post-processing, inefficient texture atlasing creating hundreds of draw calls, memory leaks in our event system, and garbage collection spikes during realm transitions that froze the game for 800ms.

Profiling with Unity and Android Tools

We used Unity Profiler connected to Android devices via ADB to identify bottlenecks: 51% GPU time spent on post-processing (bloom, vignette, color grading layered inefficiently), 28% on particle systems (instantiating/destroying instead of pooling), 300-800ms GC spikes every 30 seconds (string allocations in Update loops, event system creating delegate garbage). Android's GPU Profiler revealed excessive texture swaps (72 per frame) and fragment shader overdraw of 4.2x average (every pixel rendered 4 times due to transparent layers).

Post-Processing Stack Optimization

Reduced post-processing from 12 effects to 4 on mobile using platform-specific build configurations. Bloom, color grading, and vignette were baked into a single custom shader instead of separate passes—one shader calculating all three effects simultaneously reduced GPU time by 68%. Implemented dynamic quality scaling: when framerate drops below 30fps, effects automatically disable (starting with most expensive) until performance recovers, then gradually re-enable. Added quality presets based on device tier detected at launch.

Memory Management and GC Elimination

Implemented object pooling for all frequently instantiated objects (particles, UI elements, temporary effects)—eliminated 95% of allocations. Replaced string concatenation with StringBuilder and cached all dialog text. Moved from event delegates (which allocate) to lightweight enum-based message systems. Aggressively unloaded unused realm assets during transitions using Addressables. Result: 60fps on flagship devices, 45fps on mid-range, 30fps on budget phones, with GC spikes reduced to 8ms (imperceptible). Load time dropped from 8 seconds to 1.2 seconds.