unity-ui
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUnity UI Systems
Unity UI系统
Unity provides three UI frameworks. UI Toolkit is the recommended system for new projects. uGUI remains supported for legacy and certain runtime use cases. IMGUI is strictly for Editor tooling and debugging.
Unity提供三种UI框架。UI Toolkit是新项目推荐使用的系统。uGUI仍支持传统项目及特定运行时场景。IMGUI严格用于编辑器工具开发与调试。
UI System Comparison
UI系统对比
| Feature | UI Toolkit | uGUI (Canvas) | IMGUI |
|---|---|---|---|
| Recommended for new projects | Yes | No (legacy) | No |
| Runtime game UI | Yes | Yes | Not recommended |
| Editor extensions | Yes | No | Yes |
| Approach | Web-inspired (UXML + USS + C#) | GameObject + Component | Code-only (OnGUI) |
| Layout system | Flexbox (Yoga) | RectTransform + Anchors | Immediate mode |
| Styling | USS stylesheets | Per-component properties | GUIStyle / GUISkin |
| Visual authoring | UI Builder | Scene View | None |
| Performance | Optimized retained mode | Canvas batching | Redraws every frame |
| Data binding | SerializedObject + Runtime binding | Manual via code | Manual via code |
| World-space UI | Supported | Canvas World Space mode | Not supported |
| Input integration | Pointer/Keyboard events | EventSystem + Raycasters | Event.current |
Decision guide:
- New runtime UI (menus, HUD, inventory) --> UI Toolkit
- New Editor windows / inspectors --> UI Toolkit
- Existing project with uGUI --> Continue with uGUI, migrate incrementally
- Quick debug overlays in Editor --> IMGUI
- World-space UI on 3D objects --> Either UI Toolkit or uGUI World Space Canvas
| 特性 | UI Toolkit | uGUI (Canvas) | IMGUI |
|---|---|---|---|
| 推荐用于新项目 | 是 | 否(传统) | 否 |
| 游戏运行时UI | 是 | 是 | 不推荐 |
| 编辑器扩展 | 是 | 否 | 是 |
| 实现方式 | 类Web技术(UXML + USS + C#) | 游戏对象+组件 | 纯代码(OnGUI) |
| 布局系统 | Flexbox(Yoga) | RectTransform + 锚点 | 即时模式 |
| 样式设置 | USS样式表 | 组件独立属性 | GUIStyle / GUISkin |
| 可视化创作 | UI Builder | 场景视图 | 无 |
| 性能 | 优化的保留模式 | Canvas批处理 | 每帧重绘 |
| 数据绑定 | SerializedObject + 运行时绑定 | 代码手动实现 | 代码手动实现 |
| 世界空间UI | 支持 | Canvas世界空间模式 | 不支持 |
| 输入集成 | 指针/键盘事件 | EventSystem + 射线检测 | Event.current |
选择指南:
- 新的运行时UI(菜单、HUD、背包)→ UI Toolkit
- 新的编辑器窗口/检视面板 → UI Toolkit
- 已有uGUI的项目 → 继续使用uGUI,逐步迁移
- 编辑器中快速调试覆盖层 → IMGUI
- 3D对象上的世界空间UI → UI Toolkit 或 uGUI世界空间Canvas
UI Toolkit
UI Toolkit
UI Toolkit is Unity's modern UI framework inspired by web technologies. It uses UXML for structure, USS for styling, and C# for logic.
UI Toolkit是Unity受Web技术启发的现代UI框架。它使用UXML定义结构,USS设置样式,C#编写逻辑。
Core Architecture
核心架构
UIDocument (MonoBehaviour on GameObject)
--> VisualTreeAsset (.uxml) -- defines structure
--> StyleSheet (.uss) -- defines appearance
--> C# script -- defines behaviorAll UI elements inherit from . The root is accessed via .
VisualElementrootVisualElementUIDocument (MonoBehaviour on GameObject)
--> VisualTreeAsset (.uxml) -- 定义结构
--> StyleSheet (.uss) -- 定义外观
--> C# script -- 定义行为所有UI元素都继承自。可通过访问根元素。
VisualElementrootVisualElementUXML Structure
UXML结构
UXML defines the UI hierarchy declaratively:
xml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:Style src="MainMenu.uss" />
<ui:VisualElement name="root-container" class="container">
<ui:Label text="Game Menu" class="title" />
<ui:Button text="Play" name="play-button" class="menu-btn" />
<ui:Button text="Settings" name="settings-button" class="menu-btn" />
<ui:Toggle label="Fullscreen" name="fullscreen-toggle" />
<ui:Slider label="Volume" low-value="0" high-value="100" name="volume-slider" />
<ui:TextField label="Player Name" name="player-name" />
</ui:VisualElement>
</ui:UXML>Key points:
- is the standard namespace
xmlns:ui="UnityEngine.UIElements" - Reference USS files with
<ui:Style src="..." /> - Use attribute for C# queries,
namefor USS stylingclass - Templates can be imported:
<ui:Template src="other.uxml" name="other" />
UXML声明式定义UI层级:
xml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:Style src="MainMenu.uss" />
<ui:VisualElement name="root-container" class="container">
<ui:Label text="Game Menu" class="title" />
<ui:Button text="Play" name="play-button" class="menu-btn" />
<ui:Button text="Settings" name="settings-button" class="menu-btn" />
<ui:Toggle label="Fullscreen" name="fullscreen-toggle" />
<ui:Slider label="Volume" low-value="0" high-value="100" name="volume-slider" />
<ui:TextField label="Player Name" name="player-name" />
</ui:VisualElement>
</ui:UXML>关键点:
- 是标准命名空间
xmlns:ui="UnityEngine.UIElements" - 使用引用USS文件
<ui:Style src="..." /> - 属性用于C#查询,
name用于USS样式设置class - 可导入模板:
<ui:Template src="other.uxml" name="other" />
USS Styling
USS样式
USS uses CSS-like syntax with Unity-specific extensions. All USS properties use the prefix for Unity-specific features.
-unity-css
/* Type selector */
Button {
background-color: #2D2D2D;
border-radius: 4px;
padding: 8px 16px;
-unity-font-style: bold;
}
/* Class selector */
.menu-btn {
width: 200px;
height: 40px;
margin: 4px 0;
font-size: 16px;
color: #FFFFFF;
}
/* Name selector */
#play-button {
background-color: #4CAF50;
}
/* Pseudo-class */
.menu-btn:hover {
background-color: #555555;
scale: 1.05 1.05;
}
.menu-btn:active {
background-color: #333333;
}
.menu-btn:disabled {
opacity: 0.5;
}
/* Descendant selector */
.container > Label {
-unity-text-align: middle-center;
}
/* USS variables */
:root {
--primary-color: #4CAF50;
--font-large: 24px;
}
.title {
color: var(--primary-color);
font-size: var(--font-large);
}Selector types: Type (), Name (), Class (), Universal (), Descendant (), Child (), Multiple (), Pseudo-classes (, , , , ).
Button#name.class*A BA > BA.class:hover:active:focus:disabled:checkedLayout is Flexbox-based: Use , , , , , , . Default direction is .
flex-directionflex-growflex-shrinkjustify-contentalign-itemsalign-selfflex-wrapcolumnUSS使用类CSS语法,并带有Unity特定扩展。所有Unity专属特性的USS属性均使用前缀。
-unity-css
/* Type selector */
Button {
background-color: #2D2D2D;
border-radius: 4px;
padding: 8px 16px;
-unity-font-style: bold;
}
/* Class selector */
.menu-btn {
width: 200px;
height: 40px;
margin: 4px 0;
font-size: 16px;
color: #FFFFFF;
}
/* Name selector */
#play-button {
background-color: #4CAF50;
}
/* Pseudo-class */
.menu-btn:hover {
background-color: #555555;
scale: 1.05 1.05;
}
.menu-btn:active {
background-color: #333333;
}
.menu-btn:disabled {
opacity: 0.5;
}
/* Descendant selector */
.container > Label {
-unity-text-align: middle-center;
}
/* USS variables */
:root {
--primary-color: #4CAF50;
--font-large: 24px;
}
.title {
color: var(--primary-color);
font-size: var(--font-large);
}选择器类型: 类型选择器()、名称选择器()、类选择器()、通用选择器()、后代选择器()、子选择器()、复合选择器()、伪类(, , , , )。
Button#name.class*A BA > BA.class:hover:active:focus:disabled:checked布局基于Flexbox: 使用、、、、、、。默认方向为。
flex-directionflex-growflex-shrinkjustify-contentalign-itemsalign-selfflex-wrapcolumnC# Setup and Interaction
C#设置与交互
csharp
using UnityEngine;
using UnityEngine.UIElements;
public class MainMenuController : MonoBehaviour
{
[SerializeField] private UIDocument uiDocument;
private Button playButton;
private Button settingsButton;
private Toggle fullscreenToggle;
private Slider volumeSlider;
private TextField playerNameField;
private void OnEnable()
{
var root = uiDocument.rootVisualElement;
// Query single elements by name
playButton = root.Q<Button>("play-button");
settingsButton = root.Q<Button>("settings-button");
fullscreenToggle = root.Q<Toggle>("fullscreen-toggle");
volumeSlider = root.Q<Slider>("volume-slider");
playerNameField = root.Q<TextField>("player-name");
// Register click callbacks
playButton.RegisterCallback<ClickEvent>(OnPlayClicked);
settingsButton.RegisterCallback<ClickEvent>(OnSettingsClicked);
// Register value change callbacks
fullscreenToggle.RegisterValueChangedCallback(OnFullscreenChanged);
volumeSlider.RegisterValueChangedCallback(OnVolumeChanged);
// Query multiple elements by class
var allButtons = root.Query<Button>(className: "menu-btn").ToList();
}
private void OnDisable()
{
playButton.UnregisterCallback<ClickEvent>(OnPlayClicked);
settingsButton.UnregisterCallback<ClickEvent>(OnSettingsClicked);
fullscreenToggle.UnregisterValueChangedCallback(OnFullscreenChanged);
volumeSlider.UnregisterValueChangedCallback(OnVolumeChanged);
}
private void OnPlayClicked(ClickEvent evt) => Debug.Log("Play clicked");
private void OnSettingsClicked(ClickEvent evt) => Debug.Log("Settings clicked");
private void OnFullscreenChanged(ChangeEvent<bool> evt)
{
Screen.fullScreen = evt.newValue;
}
private void OnVolumeChanged(ChangeEvent<float> evt)
{
AudioListener.volume = evt.newValue / 100f;
}
}Programmatic UI creation (no UXML):
csharp
private void CreateUIFromCode()
{
var root = uiDocument.rootVisualElement;
var container = new VisualElement();
container.AddToClassList("container");
root.Add(container);
var label = new Label("Created from C#");
container.Add(label);
var button = new Button(() => Debug.Log("Clicked")) { text = "Click Me" };
button.name = "dynamic-button";
container.Add(button);
}csharp
using UnityEngine;
using UnityEngine.UIElements;
public class MainMenuController : MonoBehaviour
{
[SerializeField] private UIDocument uiDocument;
private Button playButton;
private Button settingsButton;
private Toggle fullscreenToggle;
private Slider volumeSlider;
private TextField playerNameField;
private void OnEnable()
{
var root = uiDocument.rootVisualElement;
// 通过名称查询单个元素
playButton = root.Q<Button>("play-button");
settingsButton = root.Q<Button>("settings-button");
fullscreenToggle = root.Q<Toggle>("fullscreen-toggle");
volumeSlider = root.Q<Slider>("volume-slider");
playerNameField = root.Q<TextField>("player-name");
// 注册点击回调
playButton.RegisterCallback<ClickEvent>(OnPlayClicked);
settingsButton.RegisterCallback<ClickEvent>(OnSettingsClicked);
// 注册值变更回调
fullscreenToggle.RegisterValueChangedCallback(OnFullscreenChanged);
volumeSlider.RegisterValueChangedCallback(OnVolumeChanged);
// 通过类查询多个元素
var allButtons = root.Query<Button>(className: "menu-btn").ToList();
}
private void OnDisable()
{
playButton.UnregisterCallback<ClickEvent>(OnPlayClicked);
settingsButton.UnregisterCallback<ClickEvent>(OnSettingsClicked);
fullscreenToggle.UnregisterValueChangedCallback(OnFullscreenChanged);
volumeSlider.UnregisterValueChangedCallback(OnVolumeChanged);
}
private void OnPlayClicked(ClickEvent evt) => Debug.Log("Play clicked");
private void OnSettingsClicked(ClickEvent evt) => Debug.Log("Settings clicked");
private void OnFullscreenChanged(ChangeEvent<bool> evt)
{
Screen.fullScreen = evt.newValue;
}
private void OnVolumeChanged(ChangeEvent<float> evt)
{
AudioListener.volume = evt.newValue / 100f;
}
}程序化创建UI(无需UXML):
csharp
private void CreateUIFromCode()
{
var root = uiDocument.rootVisualElement;
var container = new VisualElement();
container.AddToClassList("container");
root.Add(container);
var label = new Label("Created from C#");
container.Add(label);
var button = new Button(() => Debug.Log("Clicked")) { text = "Click Me" };
button.name = "dynamic-button";
container.Add(button);
}Event System
事件系统
UI Toolkit events propagate in two phases:
- Trickle-down -- from root to target element
- Bubble-up -- from target back to root
csharp
// Default: bubble-up phase
element.RegisterCallback<PointerDownEvent>(OnPointerDown);
// Trickle-down phase (parent reacts before children)
element.RegisterCallback<PointerDownEvent>(OnPointerDown, TrickleDown.TrickleDown);
// Pass custom data to callbacks
element.RegisterCallback<ClickEvent, string>(OnClickWithData, "my-data");
// Set value without triggering ChangeEvent
myControl.SetValueWithoutNotify(newValue);UI Toolkit事件分为两个传播阶段:
- 向下渗透 -- 从根元素到目标元素
- 向上冒泡 -- 从目标元素返回根元素
csharp
// 默认:向上冒泡阶段
element.RegisterCallback<PointerDownEvent>(OnPointerDown);
// 向下渗透阶段(父元素先于子元素响应)
element.RegisterCallback<PointerDownEvent>(OnPointerDown, TrickleDown.TrickleDown);
// 向回调传递自定义数据
element.RegisterCallback<ClickEvent, string>(OnClickWithData, "my-data");
// 设置值但不触发ChangeEvent
myControl.SetValueWithoutNotify(newValue);Data Binding
数据绑定
SerializedObject binding (Editor / Inspector UI):
csharp
// In UXML: <ui:IntegerField binding-path="m_Health" label="Health" />
// In C#:
var healthField = new IntegerField("Health") { bindingPath = "m_Health" };
root.Add(healthField);
root.Bind(new SerializedObject(targetComponent));Bindable objects: MonoBehaviour, ScriptableObject, native Unity types, primitives.
Only the property of elements can be bound.
valueINotifyValueChangedRuntime binding connects plain C# objects to UI controls, works in both Editor and runtime contexts. Set data sources on elements and define binding modes for synchronization direction.
See: references/ui-data-binding.md
SerializedObject绑定(编辑器/检视面板UI):
csharp
// 在UXML中:<ui:IntegerField binding-path="m_Health" label="Health" />
// 在C#中:
var healthField = new IntegerField("Health") { bindingPath = "m_Health" };
root.Add(healthField);
root.Bind(new SerializedObject(targetComponent));可绑定对象:MonoBehaviour、ScriptableObject、Unity原生类型、基本数据类型。仅元素的属性可被绑定。
INotifyValueChangedvalue运行时绑定将普通C#对象与UI控件关联,在编辑器和运行时环境均有效。可在元素上设置数据源,并定义绑定模式以指定同步方向。
参考:references/ui-data-binding.md
Manipulators
操作器(Manipulators)
Manipulators encapsulate event-handling logic, separating interaction from UI code:
csharp
public class DragManipulator : PointerManipulator
{
private Vector3 startPosition;
private bool isDragging;
public DragManipulator(VisualElement target)
{
this.target = target;
}
protected override void RegisterCallbacksOnTarget()
{
target.RegisterCallback<PointerDownEvent>(OnPointerDown);
target.RegisterCallback<PointerMoveEvent>(OnPointerMove);
target.RegisterCallback<PointerUpEvent>(OnPointerUp);
}
protected override void UnregisterCallbacksFromTarget()
{
target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
target.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
target.UnregisterCallback<PointerUpEvent>(OnPointerUp);
}
private void OnPointerDown(PointerDownEvent evt)
{
startPosition = evt.position;
isDragging = true;
target.CapturePointer(evt.pointerId);
evt.StopPropagation();
}
private void OnPointerMove(PointerMoveEvent evt)
{
if (!isDragging) return;
var delta = evt.position - startPosition;
target.transform.position += (Vector3)delta;
startPosition = evt.position;
}
private void OnPointerUp(PointerUpEvent evt)
{
isDragging = false;
target.ReleasePointer(evt.pointerId);
evt.StopPropagation();
}
}
// Usage:
myElement.AddManipulator(new DragManipulator(myElement));Built-in manipulator classes: (base), , , , , .
ManipulatorPointerManipulatorMouseManipulatorClickableContextualMenuManipulatorKeyboardNavigationManipulator操作器封装了事件处理逻辑,将交互与UI代码分离:
csharp
public class DragManipulator : PointerManipulator
{
private Vector3 startPosition;
private bool isDragging;
public DragManipulator(VisualElement target)
{
this.target = target;
}
protected override void RegisterCallbacksOnTarget()
{
target.RegisterCallback<PointerDownEvent>(OnPointerDown);
target.RegisterCallback<PointerMoveEvent>(OnPointerMove);
target.RegisterCallback<PointerUpEvent>(OnPointerUp);
}
protected override void UnregisterCallbacksFromTarget()
{
target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
target.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
target.UnregisterCallback<PointerUpEvent>(OnPointerUp);
}
private void OnPointerDown(PointerDownEvent evt)
{
startPosition = evt.position;
isDragging = true;
target.CapturePointer(evt.pointerId);
evt.StopPropagation();
}
private void OnPointerMove(PointerMoveEvent evt)
{
if (!isDragging) return;
var delta = evt.position - startPosition;
target.transform.position += (Vector3)delta;
startPosition = evt.position;
}
private void OnPointerUp(PointerUpEvent evt)
{
isDragging = false;
target.ReleasePointer(evt.pointerId);
evt.StopPropagation();
}
}
// 使用方式:
myElement.AddManipulator(new DragManipulator(myElement));内置操作器类: (基类)、、、、、。
ManipulatorPointerManipulatorMouseManipulatorClickableContextualMenuManipulatorKeyboardNavigationManipulatorCustom Controls
自定义控件
csharp
// Unity 6+ recommended pattern: [UxmlElement] attribute (replaces deprecated UxmlFactory/UxmlTraits)
[UxmlElement]
public partial class HealthBar : VisualElement
{
[UxmlAttribute]
public float MaxHealth { get; set; } = 100f;
private VisualElement fillBar;
private float currentHealth;
public float CurrentHealth
{
get => currentHealth;
set
{
currentHealth = Mathf.Clamp(value, 0, MaxHealth);
fillBar.style.width = Length.Percent(currentHealth / MaxHealth * 100f);
}
}
public HealthBar()
{
AddToClassList("health-bar");
fillBar = new VisualElement();
fillBar.AddToClassList("health-bar__fill");
Add(fillBar);
}
}csharp
// Unity 6+推荐模式:[UxmlElement]属性(替代已弃用的UxmlFactory/UxmlTraits)
[UxmlElement]
public partial class HealthBar : VisualElement
{
[UxmlAttribute]
public float MaxHealth { get; set; } = 100f;
private VisualElement fillBar;
private float currentHealth;
public float CurrentHealth
{
get => currentHealth;
set
{
currentHealth = Mathf.Clamp(value, 0, MaxHealth);
fillBar.style.width = Length.Percent(currentHealth / MaxHealth * 100f);
}
}
public HealthBar()
{
AddToClassList("health-bar");
fillBar = new VisualElement();
fillBar.AddToClassList("health-bar__fill");
Add(fillBar);
}
}uGUI / Canvas System (Legacy)
uGUI / Canvas系统(传统)
uGUI is Unity's older GameObject-based UI system. It uses Canvas, RectTransform, and the EventSystem.
uGUI是Unity基于游戏对象的旧版UI系统。它使用Canvas、RectTransform和EventSystem。
Canvas Render Modes
Canvas渲染模式
| Mode | Description | Use Case |
|---|---|---|
| Screen Space - Overlay | Renders on top of everything, scales with screen | Standard HUD, menus |
| Screen Space - Camera | Rendered by a specific camera, affected by perspective | UI with depth effects |
| World Space | Canvas as a 3D object in the scene | In-world displays, VR UI |
| 模式 | 描述 | 使用场景 |
|---|---|---|
| 屏幕空间 - 覆盖 | 渲染在所有内容上方,随屏幕缩放 | 标准HUD、菜单 |
| 屏幕空间 - 相机 | 由指定相机渲染,受透视影响 | 带有深度效果的UI |
| 世界空间 | Canvas作为场景中的3D对象 | 场景内显示屏、VR UI |
Core Components
核心组件
Visual: Text, Image, RawImage
Interaction: Button, Toggle, ToggleGroup, Slider, Scrollbar, Dropdown, InputField, ScrollRect
Layout: HorizontalLayoutGroup, VerticalLayoutGroup, GridLayoutGroup, ContentSizeFitter, AspectRatioFitter, LayoutElement
视觉类: Text、Image、RawImage
交互类: Button、Toggle、ToggleGroup、Slider、Scrollbar、Dropdown、InputField、ScrollRect
布局类: HorizontalLayoutGroup、VerticalLayoutGroup、GridLayoutGroup、ContentSizeFitter、AspectRatioFitter、LayoutElement
RectTransform and Anchoring
RectTransform与锚点
All uGUI elements use RectTransform instead of Transform. Anchors define how an element positions relative to its parent:
- Anchor Min/Max as fractions (0.0 = left/bottom, 1.0 = right/top)
- Together anchors: fixed position (Pos X, Pos Y, Width, Height)
- Separated anchors: stretching (Left, Right, Top, Bottom padding)
- Pivot: center point for rotation and scaling
所有uGUI元素使用RectTransform而非Transform。锚点定义元素相对于父元素的定位方式:
- Anchor Min/Max为比例值(0.0=左/下,1.0=右/上)
- 锚点重合:固定位置(Pos X、Pos Y、宽度、高度)
- 锚点分离:拉伸模式(左、右、上、下内边距)
- Pivot:旋转和缩放的中心点
uGUI Example
uGUI示例
csharp
using UnityEngine;
using UnityEngine.UI;
public class MenuManager : MonoBehaviour
{
[SerializeField] private Button playButton;
[SerializeField] private Slider volumeSlider;
[SerializeField] private Toggle muteToggle;
private void OnEnable()
{
playButton.onClick.AddListener(OnPlayClicked);
volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
muteToggle.onValueChanged.AddListener(OnMuteToggled);
}
private void OnDisable()
{
playButton.onClick.RemoveListener(OnPlayClicked);
volumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
muteToggle.onValueChanged.RemoveListener(OnMuteToggled);
}
private void OnPlayClicked() => Debug.Log("Play");
private void OnVolumeChanged(float value) => AudioListener.volume = value;
private void OnMuteToggled(bool muted) => AudioListener.pause = muted;
}csharp
using UnityEngine;
using UnityEngine.UI;
public class MenuManager : MonoBehaviour
{
[SerializeField] private Button playButton;
[SerializeField] private Slider volumeSlider;
[SerializeField] private Toggle muteToggle;
private void OnEnable()
{
playButton.onClick.AddListener(OnPlayClicked);
volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
muteToggle.onValueChanged.AddListener(OnMuteToggled);
}
private void OnDisable()
{
playButton.onClick.RemoveListener(OnPlayClicked);
volumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
muteToggle.onValueChanged.RemoveListener(OnMuteToggled);
}
private void OnPlayClicked() => Debug.Log("Play");
private void OnVolumeChanged(float value) => AudioListener.volume = value;
private void OnMuteToggled(bool muted) => AudioListener.pause = muted;
}Draw Order
绘制顺序
Elements render in Hierarchy order: first child drawn first, last child drawn on top. Reorder with , , .
Transform.SetAsFirstSibling()SetAsLastSibling()SetSiblingIndex()See: references/ugui-legacy.md
元素按层级顺序渲染:第一个子元素最先绘制,最后一个子元素绘制在最上层。可使用、、调整顺序。
Transform.SetAsFirstSibling()SetAsLastSibling()SetSiblingIndex()参考:references/ugui-legacy.md
Anti-Patterns
反模式
| Anti-Pattern | Problem | Correct Approach |
|---|---|---|
| Using inline styles everywhere | Per-element memory overhead | Use USS files for shared styles |
Universal selectors in complex USS ( | Poor selector performance at scale | Use BEM class naming, child selectors |
Heavy | Mouse movement invalidates entire hierarchies | Limit |
Calling | Double-binding, automatic binding occurs after return | Let auto-binding handle it, or call Bind only on manually created UI |
| Rebuilding entire UI every frame | Defeats retained-mode benefits | Update only changed elements |
| Multiple Canvases with dynamic content (uGUI) | Canvas rebuild batches on any child change | Split static and dynamic UI into separate Canvases |
| Not unregistering callbacks | Memory leaks, stale references | Always unregister in |
| Using IMGUI for runtime game UI | Redraws every frame, poor performance | Use UI Toolkit or uGUI |
| Forgetting EventSystem in scene (uGUI) | No input events processed | Ensure one EventSystem exists in scene |
| 反模式 | 问题 | 正确做法 |
|---|---|---|
| 随处使用内联样式 | 每个元素都有内存开销 | 使用USS文件管理共享样式 |
复杂USS中使用通用选择器( | 大规模场景下选择器性能差 | 使用BEM命名规范、子选择器 |
在包含大量子元素的元素上使用 | 鼠标移动会导致整个层级失效 | 仅在叶子元素上使用 |
在 | 双重绑定,返回后会自动执行绑定 | 让自动绑定处理,或仅在手动创建的UI上调用Bind |
| 每帧重建整个UI | 失去保留模式的优势 | 仅更新发生变化的元素 |
| uGUI中多个Canvas包含动态内容 | 任何子元素变化都会导致Canvas重建批处理 | 将静态和动态UI拆分到不同Canvas |
| 不注销回调 | 内存泄漏、无效引用 | 始终在 |
| 使用IMGUI开发游戏运行时UI | 每帧重绘,性能差 | 使用UI Toolkit或uGUI |
| uGUI场景中缺少EventSystem | 无法处理输入事件 | 确保场景中存在一个EventSystem |
Key API Quick Reference
核心API速查
UI Toolkit
UI Toolkit
| API | Purpose |
|---|---|
| MonoBehaviour that hosts a VisualTreeAsset |
| Root of the visual tree |
| Query single element by name |
| Query single element by class |
| Query multiple elements |
| Register event handler |
| Remove event handler |
| Listen for value changes |
| Set value silently |
| Add USS class |
| Remove USS class |
| Attach event manipulator |
| Hide element |
| Show element |
| Create instance from UXML |
| Bind to SerializedObject |
| API | 用途 |
|---|---|
| 承载VisualTreeAsset的MonoBehaviour |
| 视觉树的根元素 |
| 通过名称查询单个元素 |
| 通过类查询单个元素 |
| 查询多个元素 |
| 注册事件处理器 |
| 移除事件处理器 |
| 监听值变化 |
| 静默设置值 |
| 添加USS类 |
| 移除USS类 |
| 附加事件操作器 |
| 隐藏元素 |
| 显示元素 |
| 从UXML创建实例 |
| 绑定到SerializedObject |
uGUI
uGUI
| API | Purpose |
|---|---|
| Root container for all uGUI elements |
| Controls UI scaling across resolutions |
| Enables input detection on Canvas |
| Central input event dispatcher |
| Transform with anchoring and sizing |
| UnityEvent for click |
| UnityEvent for toggle change |
| UnityEvent for slider change |
| Auto-layout for children |
| API | 用途 |
|---|---|
| 所有uGUI元素的根容器 |
| 控制UI在不同分辨率下的缩放 |
| 启用Canvas上的输入检测 |
| 中央输入事件调度器 |
| 带有锚点和尺寸设置的Transform |
| 点击事件的UnityEvent |
| 开关状态变化的UnityEvent |
| 滑块值变化的UnityEvent |
| 子元素自动布局 |
Related Skills
相关技能
- unity-foundations -- GameObject, Component, MonoBehaviour lifecycle
- unity-scripting -- C# patterns, SerializeField, events
- unity-input -- Input System integration with UI
- unity-foundations -- GameObject、Component、MonoBehaviour生命周期
- unity-scripting -- C#模式、SerializeField、事件
- unity-input -- 输入系统与UI集成
TextMeshPro
TextMeshPro
For all text rendering, use TextMeshPro (TMP) — not legacy . TMP uses SDF rendering for crisp text at any scale. Use for Canvas UI, for 3D world text. Use for zero-allocation updates. See references/textmeshpro.md for full API, rich text tags, font assets, and patterns.
UI.TextTextMeshProUGUITextMeshProSetText("Score: {0}", value)所有文本渲染请使用TextMeshPro(TMP)——而非传统的。TMP使用SDF渲染,可在任何缩放级别下保持文本清晰。Canvas UI使用,3D世界文本使用。使用实现零内存分配更新。完整API、富文本标签、字体资源及使用模式请参考references/textmeshpro.md。
UI.TextTextMeshProUGUITextMeshProSetText("Score: {0}", value)Additional Resources
额外资源
- UI Toolkit | USS | UXML | Data Binding | Manipulators
- uGUI Canvas | uGUI Layout
- UI Toolkit | USS | UXML | 数据绑定 | 操作器
- uGUI Canvas | uGUI布局