Loading...
Loading...
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.
npx skill4agent add josiahsiegel/claude-plugin-marketplace unity-ui-development| Factor | UGUI | UI Toolkit |
|---|---|---|
| Runtime UI | Mature, full-featured | Supported (Unity 2023+) |
| Editor UI | Not supported | Primary system for editor |
| World-space UI | Excellent (World Space Canvas) | Limited |
| Animation/Tweening | DOTween, Animator, LeanTween | USS transitions, C# manipulation |
| Styling | Per-element, manual | USS stylesheets (CSS-like) |
| Performance | Draw call heavy with many canvases | Retained mode, lighter draw calls |
| Learning curve | Lower for Unity devs | Higher (web-like paradigm) |
| VR/AR | Well-supported | Limited world-space support |
| Render Mode | Use For | Notes |
|---|---|---|
| Screen Space - Overlay | HUD, menus | Always on top, no camera needed |
| Screen Space - Camera | Post-processing on UI | Assign render camera |
| World Space | In-game signs, health bars | Set event camera for interaction |
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)anchorMinanchorMaxoffsetMinoffsetMax| Component | Purpose |
|---|---|
| Arrange children left-to-right |
| Arrange children top-to-bottom |
| Grid arrangement (inventory slots) |
| Override min/preferred/flexible size |
| Auto-resize to content |
| Maintain aspect ratio |
Layout.childForceExpandWidth/Heightusing 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);
}RemoveListenerOnDisableTMP_TextTextMeshProUGUIText<color=#FF0000><b><size=24><sprite=0>UI Toolkit Stack:
UXML -- Structure (like HTML)
USS -- Styling (like CSS)
C# -- Logic (like JavaScript)<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>.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;
}-unity-flex-direction: columntransition-durationtransition-property[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;
}
}Q<T>("name")Q<T>(className: "class")RegisterCallback<EventType>rootVisualElement// 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));
}binding-path="Health"element.SetBinding("value", new DataBinding { dataSourcePath = ... })| Pattern | UGUI Approach | UI Toolkit Approach |
|---|---|---|
| Popup dialog | Enable/disable child panel | Add/remove from visual tree |
| Scroll list | ScrollRect + VerticalLayoutGroup | ListView (virtualized) |
| Drag-and-drop | IBeginDragHandler, IDragHandler, IEndDragHandler | PointerManipulator |
| Tab system | Toggle group + panels | RadioButtonGroup + display toggling |
| Tooltip | Follow cursor panel | Manipulator + VisualElement positioning |
| Screen fade | CanvasGroup.alpha tween | USS opacity transition |
references/ugui-patterns.mdreferences/ui-toolkit-advanced.md