When optimizing UGUI, the first question to answer is: where is the cost actually coming from? Without this understanding, optimization efforts are likely to be scattered and ineffective.
Problem / Scenario
Mobile game teams often encounter frame-rate drops and device heating as UI complexity grows. The UI system seems simple on the surface—just images and text—but the underlying cost structure is more nuanced than many developers realize.
The Two Dimensions of UI Performance
UGUI performance cost breaks down into two categories: rendering and logic.
Rendering
DrawCall
DrawCall is primarily a CPU cost. Each draw command issued to the GPU requires state setup and parameter passing. High DrawCall counts directly increase CPU usage.
Benchmark targets from real projects:
- Complex MMO-style HUD: under 30 Draw Calls
- Combat UI: single-digit Draw Calls
These targets apply when the UI is composited on top of a 3D scene. Full-screen UIs without scene rendering can have a slightly relaxed budget.
Overdraw
Overdraw measures how many times screen pixels are redrawn by UI elements. Every image or button placed on screen contributes. Translucent UIs (common in high-tech visual styles) are especially prone to Overdraw waste since the 3D scene behind must remain visible.
Logic
Three functions account for nearly all UI logic cost:
1. EventSystem.Update
Two components:
- Event detection: Every frame, Unity traverses all interactive UI elements to check for intersection with touch points. Complexity scales with the number of interactive elements.
-
Event callback logic: Code inside
onClickand similar callbacks runs within this function (though this is application logic, not UI system overhead).
2. Canvas.SendWillRenderCanvases
This function recalculates vertex data for dirty UI elements. Vertex attributes (positions, UVs, etc.) are stored in C# arrays. When text content changes—or any property affecting vertex positions changes—the arrays must be rebuilt. The data is then transferred to Mesh objects for rendering.
Key insight: This is pure main-thread C# work. The more elements change per frame, the higher the cost.
3. Canvas.BuildBatch / BatchJob
After vertex data is ready, each UI element still has its own mesh. Drawing them one by one would result in an unacceptably high DrawCall count. BuildBatch merges compatible elements into larger meshes.
Batching considers:
- Same atlas (texture)
- Same material
- Depth order in the VisibleList (sorted by Depth → Material → Atlas → Hierarchy priority)
- Whether elements overlap
- Rendering order adjustments for non-overlapping elements
The batching calculation itself has non-trivial CPU cost. However, a significant portion of BatchJobs can run on worker threads, which helps on multi-core devices.
Key Takeaway
In practice, EventSystem.Update is rarely the primary bottleneck. The usual suspects are:
- DrawCall and Overdraw on the rendering side
- SendWillRenderCanvases and BuildBatch on the logic side
Knowing which one to target is half the battle. The remaining sections in this series dive into optimization techniques for each area, using a real MMO weapon UI panel as a case study.
Top comments (0)