π Website: www.gameoptim.com
Problem / Scenario
A weapon UI panel in an MMO project had 86 Batches (DrawCalls after batching). While this might be acceptable on mid-to-high-end devices, it's problematic on low-end mobile devicesβespecially when the UI must composite with a 3D scene underneath. The question: how do we systematically reduce this number?
What We Observed
Using Unity's Frame Debugger, we traced the DrawCall distribution:
- Background elements: drawn individually
- Masking frames: several Draw Calls
- Weapon icon panel: 60+ Draw Calls (each icon had background + icon + outer frame, all separate)
The weapon icon grid was the clear bottleneck, accounting for the majority of DrawCalls.
How to Analyze It
1. Start with atlas packing
Atlas packing is the standard first step. UGUI provides the Legacy Sprite Packer:
- Enable in Edit β Project Settings β Editor β Sprite Packer β Always Enable (Legacy)
- Set Packing Tag on Sprite assets to group them
- View results via Window β 2D β Sprite Packer
We tagged background images as main and weapon sprites as weapon.
Result after atlas packing: 86 β 60 Batches
The circular background elements batched together. Each icon went from 3 draws to 2 (background + frame batched, icon separate). But 48 Draw Calls for the icon grid was still too highβwe expected fewer.
2. Investigate batching failure
Why wouldn't the icons batch more aggressively? The key insight: Unity can only batch adjacent, non-overlapping elements that share the same material and atlas.
The VisibleList is sorted by:
- Depth (ascending)
- Material
- Texture atlas
- Hierarchy priority
If elements overlap, reordering them would change the visual output (wrong occlusion), so they cannot be batched.
We verified this with a simple test:
- Two buttons, no overlap β 2 Draw Calls
- Two buttons, overlapping β 4 Draw Calls
3. Find the hidden overlap
In Scene view with Shaded Wireframe mode, we inspected the icon grid closely. The borders appeared very close together.
Adjusting Layout spacing from 0 to 1 didn't help. Then we noticed: the background and border elements had different Z values.
Different Z values mean different depths in the VisibleList sorting. Even if the visual difference is intentional for a floating effect, it prevents batching because elements at different depths aren't adjacent in the draw order.
Root Cause
The high DrawCall count had two causes:
- No atlas packing β each sprite was its own texture, so no batching possible
- Different Z values creating effective "overlap" β even adjacent icons couldn't batch because their sub-elements had inconsistent Z positions, breaking the adjacency requirement in the VisibleList
Optimization
- Pack atlases β group related sprites with Packing Tags
- Unify Z values β set all Z values to 0 so elements can be properly sorted and batched
- Verify with wireframe β always check Shaded Wireframe to confirm no unintended overlap
Result
DrawCall dropped from 86 to under 20.
Key Takeaway
Atlas packing is necessary but not sufficient. Batching failures often come from subtle issues like:
- Z-value differences between elements on the same visual plane
- Pixel-perfect adjacency that Unity interprets as overlap
- Hierarchy ordering that doesn't match visual ordering
Always use Frame Debugger + Shaded Wireframe to diagnose batching issues systematically.
Top comments (0)