DEV Community

Cover image for UGUI DrawCall Reduction: Atlas Packing and Batching Failure Analysis
GameOptim
GameOptim

Posted on

UGUI DrawCall Reduction: Atlas Packing and Batching Failure Analysis

🌐 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:

  1. Depth (ascending)
  2. Material
  3. Texture atlas
  4. 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:

  1. No atlas packing β€” each sprite was its own texture, so no batching possible
  2. 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

  1. Pack atlases β€” group related sprites with Packing Tags
  2. Unify Z values β€” set all Z values to 0 so elements can be properly sorted and batched
  3. 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)