Unity UI (uGUI) Interface Implementation
Unity UI (uGUI)—system working via Canvas, LayoutGroup, and EventSystem. When configured correctly, it gives stable, predictable interface with minimal draw calls. When incorrect—200+ draw calls on single inventory screen and Canvas.ForceUpdateCanvases() calls that hang for 8–12 ms every few frames.
Most uGUI performance problems are baked into Canvas architecture, not element count.
Canvas and Batching: Where Draw Calls Go
Canvas collects all UI elements into batch—group of objects rendered by one draw call. Batching condition: identical material + identical texture (Sprite Atlas) + identical depth without overlaps with foreign elements.
Three things break batching. First—texture source mixing: icon from Atlas A, button from Atlas B, text via TextMeshPro with its own font atlas. Each texture switch—new draw call. Solution: all visual elements on one screen—in one Sprite Atlas. TextMeshPro texts grouped separately, always their own batch, but at least one.
Second—nested Mask components. Each Mask in uGUI adds 2 stencil passes and breaks batch for everything inside and outside mask. For scrollable lists unavoidable, but for static elements with "cut corners" better to draw texture with needed shape than add Mask.
Third—incorrect Sibling Index order on overlapping elements. If Image A and Image B overlap and from one atlas, batch still breaks. Unity batches work only if no overlaps between elements from different atlases. This means UI element z-order affects batching same as texture atlas.
Diagnostics: Frame Debugger → Enable button → expand render tree to UI section → count draw calls on UI. Good figure for single HUD—5–15. Over 50—something wrong.
RectTransform: Rules That Save From Pain
RectTransform—basis of positioning in uGUI. Anchors and Pivot—not same thing. Anchor determines which point of parent container element attaches to. Pivot—rotation and scale point of element itself.
Typical mistake: anchors set to left top corner, element should be screen center independent of resolution. On resolution change element moves. Correct: anchor → center/middle, position via anchored position = (0, 0). Then element stays center on any resolution.
For different-resolution adaptation use Canvas Scaler. Scale With Screen Size mode with Reference Resolution 1920×1080 and Match = 0.5 (average between Width and Height)—workable base for most projects. For mobile with different aspect ratios, raise Match to 0.8–1.0 favoring Height, otherwise on iPhone with 19.5:9 ratio UI spreads horizontally.
ContentSizeFitter + VerticalLayoutGroup—combination for dynamic lists. ContentSizeFitter stretches container to content, VerticalLayoutGroup arranges child elements. Problem: each hierarchy change triggers Layout Rebuild—recalculates all element positions. For ScrollView with hundreds of elements—catastrophe. Solution—Virtual Scroll List (pool-based): keep only visible elements in memory, return rest to pool on scroll. Requires manual implementation but cuts active UI objects from hundreds to 10–15.
TextMeshPro: Fonts and Performance
TextMeshPro—standard for text in Unity UI. Uses Signed Distance Field (SDF) rendering: font looks sharp at any scale without raster. Each language needs its own Font Asset with needed glyphs.
Localization problem: Cyrillic, Chinese, Japanese need different Font Assets. When mixing languages on screen—multiple Font Assets, multiple font atlases, multiple draw calls just on text. Solution—Fallback Font Asset: main Latin font with registered Cyrillic/CJK fallback. TextMeshPro auto-uses fallback for missing glyphs, all text stays within one-two draw calls.
Atlas Population Mode: Dynamic (default) adds glyphs to atlas as encountered in text—good for dev builds, bad for production (possible microfreezes on first render of new glyph). For release use Static with pre-filled atlas via Font Asset Creator.
Case Study: 200 Draw Calls on Inventory Screen
Project came with complaint about 15% FPS drop opening inventory on mobile. Frame Debugger showed 214 draw calls for one screen with 48 item slots. Reason: each slot separate Prefab with icon from individual PNG (not atlas), TextMeshPro quantity, background frame from different PNG, and Outline component (which generates extra mesh in uGUI).
Solution: pack all icons into two Sprite Atlases (items and UI chrome separate), replace TextMeshPro Outline with SDF Outline in material settings, add Virtual Scroll List to item grid. Result: 22 draw calls for same screen. Mobile FPS returned to normal.
Styling Process
Start with Figma mockups showing dimensions, spacing, adaptation rules. Define Canvas and atlas structure. Style basic layout on RectTransforms, connect fonts and textures. Configure EventSystem and gamepad/keyboard navigation. Test on several resolutions via Game View with custom resolutions. Profile via Frame Debugger.
| Volume | Timeline |
|---|---|
| 1–3 screens (simple, no animations) | 2–5 days |
| Full indie project UI kit (10–15 screens) | 3–6 weeks |
| Complex screens with virtual scroll, drag & drop | 1–3 weeks per system |
| Multiplatform adaptation of existing UI | 1–4 weeks |
Cost determined after Figma mockup analysis and technical requirements.





