UGUI Rendering Optimization
Professional case study
UGUI Rendering Optimization
Live-game UI performance engineering across multiple companies and titles
- Bagelcode
- StudioZoo
- SZ Code Lab
- Unity
- UGUI
- NGUI
- C#
- HLSL
- Unity Profiler
- Frame Debugger
- Avg FPS
- 60 (on low-end devices)
- Peak Draw Calls
- ≈ 100
- Reference Device
- iPhone 5s · low-end Android
- Live Titles
- 8 shipped games
Challenge
Across eight live slot and casual titles — Party Slots, Vegas Party Slots, Club Vegas, Epic Diamond Slots, Jackpotjoy, Starspins, Slot & Dragons, City of Holdem, and Golden Mango Casino — the same pattern recurred. Out-game lobbies accumulated dense UI/UX requirements, and in-game features added real-time masking/clipping. The result was draw-call explosions and broken batching, which produced critical frame drops on low-end devices. The breaking point came fast on legacy targets like the iPhone 5s.
Solution
Custom UGUI components
I subclassed and rewrote UGUI components to handle complex hierarchies and real-time clipping/masking without breaking compatibility with the rest of the project. New patterns plugged into the existing prefab graph and still benefited from optimized batching.
A repeatable bottleneck-analysis routine
Every UI change went through a short checklist: profile draw calls, set-pass calls, and batches with Unity Profiler + Frame Debugger. Documenting that loop kept the bar consistent as the team grew.
Canvas hierarchy redesign
Instead of one giant canvas, I split UI into static / dynamic / overlay layers and reorganized the global atlas by layer and usage frequency, so batching collapsed naturally on most screens.
Background · Frames · Headers
(Batched aggressively)"] DynamicLayer["Dynamic Layer
Counters · Animations · Tooltips
(Re-batched per frame)"] OverlayLayer["Overlay Layer
Popups · Toasts
(On-demand canvas)"] AtlasGroup["Global Atlas Groups
per layer · per usage frequency"] Canvas --> StaticLayer Canvas --> DynamicLayer Canvas --> OverlayLayer StaticLayer --> AtlasGroup DynamicLayer --> AtlasGroup OverlayLayer --> AtlasGroup
Lightweight custom shaders
For UI elements that didn’t need full alpha testing or generic UI features, I replaced the default UI shader with lightweight HLSL shaders, cutting overdraw and shader switches on hot paths.
Tooling for non-engineers
To keep new assets from breaking the batching structure, I shipped editor inspector tooling that designers and artists could use to test placements themselves. Mistakes were caught at the moment assets were added, not at build time.
Achievements
- Rock-solid 60 FPS on low-end devices. Slot & Dragons held a steady 60 FPS with draw calls kept around ≤100 on iPhone 5s-class hardware.
- Same playbook applied across eight live titles. Bagelcode → StudioZoo → SZ Code Lab — each new project converged on the optimized structure faster than the last.
- Productivity multiplier for non-engineers. Inspector-driven scripts let design and art teams validate UI placements without an engineer in the loop, freeing core engineering time.