关于 unity-ui-development
面向 Unity 开发者的 UI 开发技能,帮助选择和实现 UGUI 或 UI Toolkit。内容涵盖系统选择、布局、事件处理、样式、数据绑定及常见界面模式。
主要功能
- 01比较 UGUI 与 UI Toolkit
- 02Canvas 设置与 RectTransform 锚点
- 03布局和事件处理模式
- 04UXML、USS 与 C# 集成
- 05UI Toolkit 数据绑定
适用场景
- 01为 Unity 项目选择 UI 系统
- 02构建自适应菜单和 HUD
- 03使用 UI Toolkit 创建编辑器界面
- 04实现列表、弹窗或拖放交互
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ josiahsiegel/ claude-plugin-marketplace --skill unity-ui-development安装后在 Claude Code 中输入/unity-ui-development确认已加载。
详细介绍
Unity UI 开发
概述
Unity 提供两种 UI 系统:UGUI(成熟的、基于 GameObject 的系统)和 UI Toolkit(受 Web 技术启发的新型保留模式系统)。本技能介绍这两种系统、各自的适用场景以及实现模式。
选择 UI 系统
| 因素 | UGUI | UI Toolkit |
|---|---|---|
| 运行时 UI | 成熟、功能全面 | 支持(Unity 2023+) |
| 编辑器 UI | 不支持 | 编辑器的主要系统 |
| 世界空间 UI | 出色(World Space Canvas) | 有限 |
| 动画/补间 | DOTween、Animator、LeanTween | USS 过渡、C# 操作 |
| 样式 | 按元素设置,手动配置 | USS 样式表(类似 CSS) |
| 性能 | Canvas 较多时绘制调用开销较大 | 保留模式,绘制调用开销较低 |
| 学习曲线 | 对 Unity 开发者来说较低 | 较高(类似 Web 的范式) |
| VR/AR | 支持良好 | 世界空间支持有限 |
**建议:**世界空间 UI、VR/AR,以及需要最大程度兼容资源商店的项目,使用 UGUI。编辑器扩展、复杂的数据驱动 UI(列表、树形结构),以及基于 Unity 2023+ 的项目,使用 UI Toolkit。
UGUI(基于 Canvas 的 UI)
Canvas 设置
| 渲染模式 | 用途 | 备注 |
|---|---|---|
| Screen Space - Overlay | HUD、菜单 | 始终显示在最上层,无需摄像机 |
| Screen Space - Camera | 对 UI 进行后期处理 | 指定渲染摄像机 |
| World Space | 游戏内标牌、生命值条 | 设置事件摄像机以支持交互 |
**性能规则:**将静态和动态 UI 分别放在不同的 Canvas 中。任何子元素发生变化时,Canvas 都会重建所有子元素。
RectTransform 锚点
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)
通过 RectTransform 锚点预设控件设置锚点(按住 Alt+Shift 还可同时设置轴心点和位置)。在代码中使用 anchorMin、anchorMax、offsetMin、offsetMax。
布局组件
| 组件 | 用途 |
|---|---|
HorizontalLayoutGroup | 从左到右排列子元素 |
VerticalLayoutGroup | 从上到下排列子元素 |
GridLayoutGroup | 网格排列(物品栏槽位) |
LayoutElement | 覆盖最小/首选/灵活尺寸 |
ContentSizeFitter | 根据内容自动调整尺寸 |
AspectRatioFitter | 保持宽高比 |
禁用 Layout.childForceExpandWidth/Height,以避免不需要的拉伸。
事件处理
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);
}
务必在 OnDisable 中调用 RemoveListener,以防止泄漏和无效引用。
TextMeshPro
始终优先使用 TextMeshPro(TMP_Text、TextMeshProUGUI),而不是旧版 Text。出现提示时导入 TMP Essentials。使用富文本标签:<color=#FF0000>、<b>、<size=24>、<sprite=0> 来显示行内图标。
UI Toolkit(USS/UXML)
架构
UI Toolkit Stack:
UXML -- Structure (like HTML)
USS -- Styling (like CSS)
C# -- Logic (like JavaScript)
UXML 结构
<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 样式
.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;
}
USS 与 CSS 的主要区别:Unity 专用属性使用 -unity- 前缀。布局采用 Flexbox 模型(默认 flex-direction: column)。使用 transition-duration、transition-property 设置动画。
C# 集成
[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 查询。
数据绑定(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));
}
在 UXML 中通过 binding-path="Health" 绑定,或在 C# 中使用 element.SetBinding("value", new DataBinding { dataSourcePath = ... }) 绑定。
常见 UI 模式
| 模式 | UGUI 方案 | UI Toolkit 方案 |
|---|---|---|
| 弹出对话框 | 启用/禁用子面板 | 在视觉树中添加/移除 |
| 滚动列表 | ScrollRect + VerticalLayoutGroup | ListView(虚拟化) |
| 拖放 | IBeginDragHandler、IDragHandler、IEndDragHandler | PointerManipulator |
| 标签页系统 | Toggle 组 + 面板 | RadioButtonGroup + 显示切换 |
| 工具提示 | 跟随光标的面板 | Manipulator + VisualElement 定位 |
| 屏幕淡入淡出 | 对 CanvasGroup.alpha 进行补间 | USS 不透明度过渡 |
更多资源
参考文件
references/ugui-patterns.md—— 高级 UGUI 模式:滚动优化、动态布局、世界空间交互、本地化、安全区域处理、屏幕适配references/ui-toolkit-advanced.md—— 自定义控件、精通 ListView/TreeView、自定义操作器、编辑器 UI 集成、主题设置、响应式布局