unity-ui-development

v2026.09.24

Unity UI development with UGUI and UI Toolkit. PROACTIVELY activate for: (1) building Unity user interfaces, (2) UGUI (Canvas, RectTransform, anchors), (3) UI Toolkit (USS, UXML, VisualElement), (4) EventSystem and input handling, (5) common UI components (buttons, scroll views, dropdowns), (6) inventory UIs, HUDs, health bars, menu systems, (7) TextMeshPro setup and rich text, (8) responsive UI (anchors, layout groups), (9) runtime UI generation, (10) world-space canvases for in-game UI. Provides: UGUI vs UI Toolkit comparison, RectTransform patterns, USS/UXML examples, layout group recipes, and TextMeshPro templates.

GitHub
Install command
npx skhub add josiahsiegel/unity-ui-development
Markdown
SKILL.md

Unity UI Development

Overview

Unity provides two UI systems: UGUI (the established GameObject-based system) and UI Toolkit (the newer retained-mode system inspired by web technologies). This skill covers both systems, when to use each, and implementation patterns.

Choosing a UI System

FactorUGUIUI Toolkit
Runtime UIMature, full-featuredSupported (Unity 2023+)
Editor UINot supportedPrimary system for editor
World-space UIExcellent (World Space Canvas)Limited
Animation/TweeningDOTween, Animator, LeanTweenUSS transitions, C# manipulation
StylingPer-element, manualUSS stylesheets (CSS-like)
PerformanceDraw call heavy with many canvasesRetained mode, lighter draw calls
Learning curveLower for Unity devsHigher (web-like paradigm)
VR/ARWell-supportedLimited world-space support

Recommendation: Use UGUI for world-space UI, VR/AR, and projects needing maximum asset store compatibility. Use UI Toolkit for editor extensions, complex data-driven UIs (lists, trees), and projects on Unity 2023+.

UGUI (Canvas-Based UI)

Canvas Setup

Render ModeUse ForNotes
Screen Space - OverlayHUD, menusAlways on top, no camera needed
Screen Space - CameraPost-processing on UIAssign render camera
World SpaceIn-game signs, health barsSet event camera for interaction

Performance rule: Separate static and dynamic UI into different Canvases. A Canvas rebuilds ALL children when any child changes.

RectTransform Anchoring

Anchor presets control how elements resize with parent:
- Stretch-Stretch: Element fills parent (full-screen backgrounds)
- Center-Center: Fixed size at center (popup dialogs)
- Bottom-Left: Fixed corner position (minimap)
- Top-Stretch: Stretches horizontally, fixed at top (nav bar)

Set anchors via the RectTransform anchor preset widget (hold Alt+Shift to also set pivot and position). Use anchorMin, anchorMax, offsetMin, offsetMax in code.

Layout Components

ComponentPurpose
HorizontalLayoutGroupArrange children left-to-right
VerticalLayoutGroupArrange children top-to-bottom
GridLayoutGroupGrid arrangement (inventory slots)
LayoutElementOverride min/preferred/flexible size
ContentSizeFitterAuto-resize to content
AspectRatioFitterMaintain aspect ratio

Disable Layout.childForceExpandWidth/Height to prevent unwanted stretching.

Event Handling

using UnityEngine.UI;
using TMPro;

[SerializeField] Button startButton;
[SerializeField] TMP_InputField nameField;
[SerializeField] Slider volumeSlider;

void OnEnable()
{
    startButton.onClick.AddListener(OnStartClicked);
    nameField.onEndEdit.AddListener(OnNameChanged);
    volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
}

void OnDisable()
{
    startButton.onClick.RemoveListener(OnStartClicked);
    nameField.onEndEdit.RemoveListener(OnNameChanged);
    volumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
}

Always RemoveListener in OnDisable to prevent leaks and ghost references.

TextMeshPro

Always use TextMeshPro (TMP_Text, TextMeshProUGUI) over legacy Text. Import TMP Essentials when prompted. Use rich text tags: <color=#FF0000>, <b>, <size=24>, <sprite=0> for inline icons.

UI Toolkit (USS/UXML)

Architecture

UI Toolkit Stack:
  UXML  -- Structure (like HTML)
  USS   -- Styling (like CSS)
  C#    -- Logic (like JavaScript)

UXML Structure

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <ui:VisualElement class="container">
        <ui:Label text="Player Stats" class="title" />
        <ui:ProgressBar name="health-bar" title="HP" high-value="100" />
        <ui:Button name="attack-btn" text="Attack" class="action-btn" />
        <ui:ListView name="inventory-list" />
    </ui:VisualElement>
</ui:UXML>

USS Styling

.container {
    flex-direction: column;
    padding: 10px;
    background-color: rgba(0, 0, 0, 0.8);
    border-radius: 8px;
}

.title {
    font-size: 24px;
    color: white;
    -unity-font-style: bold;
    margin-bottom: 10px;
}

.action-btn {
    height: 40px;
    background-color: #4CAF50;
    color: white;
    border-radius: 4px;
    transition-duration: 0.2s;
}

.action-btn:hover {
    background-color: #66BB6A;
    scale: 1.05 1.05;
}

Key USS differences from CSS: use -unity- prefix for Unity-specific properties. Flexbox is the layout model (default flex-direction: column). Use transition-duration, transition-property for animations.

C# Integration

[RequireComponent(typeof(UIDocument))]
public class StatsUI : MonoBehaviour
{
    void OnEnable()
    {
        var root = GetComponent<UIDocument>().rootVisualElement;
        var healthBar = root.Q<ProgressBar>("health-bar");
        var attackBtn = root.Q<Button>("attack-btn");
        var inventory = root.Q<ListView>("inventory-list");

        attackBtn.RegisterCallback<ClickEvent>(OnAttack);
        healthBar.value = player.Health;

        // ListView binding
        inventory.makeItem = () => new Label();
        inventory.bindItem = (element, index) =>
            ((Label)element).text = items[index].Name;
        inventory.itemsSource = items;
    }
}

Query elements with Q<T>("name") or Q<T>(className: "class"). Register callbacks with RegisterCallback<EventType>. Always query from rootVisualElement.

Data Binding (Unity 2023.2+)

// Runtime data binding with [CreateProperty] and INotifyBindablePropertyChanged
public class PlayerData : INotifyBindablePropertyChanged
{
    public event EventHandler<BindablePropertyChangedEventArgs> propertyChanged;
    private int _health;

    [CreateProperty]
    public int Health
    {
        get => _health;
        set { _health = value; Notify(); }
    }
    void Notify([CallerMemberName] string prop = "")
        => propertyChanged?.Invoke(this, new BindablePropertyChangedEventArgs(prop));
}

Bind in UXML with binding-path="Health" or in C# with element.SetBinding("value", new DataBinding { dataSourcePath = ... }).

Common UI Patterns

PatternUGUI ApproachUI Toolkit Approach
Popup dialogEnable/disable child panelAdd/remove from visual tree
Scroll listScrollRect + VerticalLayoutGroupListView (virtualized)
Drag-and-dropIBeginDragHandler, IDragHandler, IEndDragHandlerPointerManipulator
Tab systemToggle group + panelsRadioButtonGroup + display toggling
TooltipFollow cursor panelManipulator + VisualElement positioning
Screen fadeCanvasGroup.alpha tweenUSS opacity transition

Additional Resources

Reference Files

  • references/ugui-patterns.md -- Advanced UGUI patterns: scroll optimization, dynamic layouts, world-space interaction, localization, safe area handling, screen adaptation
  • references/ui-toolkit-advanced.md -- Custom controls, ListView/TreeView mastery, custom manipulators, editor UI integration, theming, responsive layouts
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

plugins/unity-master/skills/unity-ui-development

Default branch

main

Latest commit

5a1b112

Tree SHA

376c8e0