Version: Unity 6.0 (6000.0)
语言 : 中文
Migrate custom controls from an earlier version to Unity 6
从即时模式 GUI (IMGUI) 迁移到 UI 工具包

从 Unity UI (uGUI) 迁移到 UI 工具包

本页面将指导在 Unity__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
See in Glossary
(uGUI) 方面有经验的开发人员过渡到新的 UI 工具包系统。文中探讨了 uGUI 和 UI 工具包之间的异同。

由于 uGUI 是一个仅限运行时 UI 系统,因此本页面侧重于运行时 UI。UI 工具包可以创建运行时和 Editor UI。本指南适用于 UI 工具包的两个用例。

UI 层级结构

uGUI 和 UI 工具包均在层级树结构内构建和维护 UI。在 UGUI 中,此层级结构中的所有元素均作为单独的游戏对象在层级视图面板中可见。在 UI 工具包中,视觉元素被组织到视觉树中视觉树在面板中不可见。

要在 UI 工具包中查看和调试 UI 层级结构,您可以使用 UI 调试器。您可以在窗口 (Window) > UI 工具箱 (UI Toolkit) > 调试器 (Debugger) 下的编辑器工具栏中找到 UI 调试器。

UI 调试器
UI 调试器

主要差异

画布与 UIDocument

uGUI 中的 Canvas 组件类似于 UI 工具包中的 UIDocument 组件。两者都是附加到游戏对象的 MonoBehaviour。

在 uGUI 中,Canvas 组件位于 UI 树的根目录。它与 Canvas Scaler 组件一起确定下方 UI 的排序顺序、渲染和缩放模式。

在 UI 工具包中,UIDocument 组件包含对 PanelSettings 对象的引用。PanelSettings 包含 UI 的渲染设置,包括缩放模式和排序顺序。多个 UIDocument 组件可以指向同一个 PanelSettings 对象,这是一种在同一场景中使用多个 UI 屏幕时的性能优化。

面板设置
面板设置

在 UGUI 中,UI 树层级结构位于包含 Canvas 组件的游戏对象下方。在 UI 工具包中,UIDocument 组件包含对视觉树根元素的引用。

UIDocument 组件还包含对定义 UI 布局的 XML 文件的引用,在运行时从中构建视觉树。有关更多信息,请参阅创建 UI 部分。

注意:对于 Editor UI,不需要 UIDocument 组件。可以从 EditorWindow 派生自定义类,然后实现 CreateGUI()。有关实际示例,请参阅有关创建自定义 Editor 窗口的指南。

游戏对象组件与视觉元素

UI 工具包将 UI 元素视为控件或视觉元素。UI 元素的示例如下:

  • 控件
  • Buttons(按钮)
  • 文本标签

uGUI 从游戏对象构建 UI 层级结构。添加新的 UI 元素需要向层级结构添加新的游戏对象。各个控件作为 MonoBehaviour 组件实现。

在 UI 工具包中,视觉树是虚拟的,不使用游戏对象。您不能再在层级结构视图中构建或查看 UI 层级结构,但它消除了为每个 UI 元素使用游戏对象所带来的开销。

在 uGUI 中,UI 元素(直接或间接)从 UIBehavior 基类派生。类似地,在 UI 工具包中,所有 UI 元素都派生自名为 VisualElement 的基类。关键区别在于 VisualElement 类并非派生自 MonoBehaviour。不能将视觉元素附加到游戏对象。

在脚本中使用 UI 工具包控件与使用 uGUI 控件非常相似。

下表对比展示了 UGUI 中的 UI 控件和 UI 工具包中对应控件的常见脚本交互。

操作 uGUI UI 工具包
将文本写入标签 m_Label.text = "My Text"; m_Label.text = "My Text";
读取切换状态 bool isToggleChecked = m_Toggle.isOn; bool isToggleChecked = m_Toggle.value;
为按钮指定回调 m_Button.onClick.AddListener(MyCallbackFunc); m_Button.clicked += MyCallbackFunc_1;
或者
m_Button.RegisterCallback<ClickEvent>(MyCallbackFunc_2);

要了解有关控件及其属性和事件的更多信息,请参阅控件概述页面。

访问 UI 元素

在 uGUI 中,脚本可通过两种方式访问 UI 元素:

  • 在编辑器中分配对 UI 组件的引用。
  • 使用 helper 函数(例如 GetComponentInChildren<T>())在层级结构中查找组件。

由于 UI 工具包中没有游戏对象或组件,因此无法直接为编辑器中的控件指定引用。它们必须使用查询函数在运行时解析。相反,应通过 UIDocument 组件访问视觉树。

UIDocument 是一个 MonoBehaviour,因此您可以将其指定为引用,使其成为预制件的一部分。UIDocument 组件具有对根视觉元素的引用。脚本可从根中按类型或名称查找子元素,类似于 uGUI。

下表对比展示了在 Unity UI 和 UI 工具包中访问 UI 控件的情况

操作 uGUI UI 工具包
按名称查找 UI 元素 transform.FindChild("childName"); rootVisualElement.Query("childName");
按类型查找 UI 元素 transform.GetComponentInChildren<Button>(); rootVisualElement.Query<Button>();
在编辑器中直接指定引用 可能 不可能

创建 UI

uGUI 和 UI 工具包之间的最大区别之一是创建用户界面。

uGUI 和 UI 工具包都允许您可视化地构建 UI 并在 Editor 中进行预览。在 uGUI 中,UI 以及附加到各个 UI 控件的任何逻辑脚本都保存在预制件中。

在 UI 工具包中,UI 布局在 UI Builder 中创建,然后保存为一个或多个 XML 文件。在运行时,UIDocument 组件会加载 Visual Tree 在内存中组装的 UXML 文件。

与 uGUI 类似,您也可以直接从脚本创建 UI 控件,并在运行时将控件添加到视觉树中。

预制件

uGUI 将游戏对象用于包含视觉效果和逻辑的各个 UI 控件和预制件。UI 工具包采用不同的方法实现可重用,因为它将逻辑和布局分开。您可以通过 UXML 和自定义控件创建可重用的 UI 组件。

要在 UI 工具包中创建与预制件类似的模板,请执行以下操作:

  1. 为部分 UI 元素创建 XML 文件。
  2. 创建一个具有 UIDocument 组件的游戏对象。
  3. 在游戏对象中引用 UXML 文件。
  4. 向同一游戏对象添加处理 UI 组件逻辑的脚本。
  5. 将此游戏对象保存为预制件。

UV 布局

在 uGUI 中,在屏幕上排列各个 UI 元素是一个手动过程。默认情况下,UI 控件是自由浮动的,并且仅受其直接父级的影响。同一父级下的其他 UI 控件不会影响其同级控件的位置或大小。轴心和锚点可控制元素的位置和大小。

UI 工具包布局系统受网页设计的影响,并基于自动生成布局。默认情况下,自动布局系统会影响所有元素,一个元素的大小和位置会影响同一父级下的其他元素。

UI 工具包中的默认行为相当于将所有元素放在 UGUI 中的 VerticalLayoutGroup 中,并为每个元素添加一个 LayoutElement 组件。

您可以通过更改视觉元素的 IStyle position 属性来禁用自动生成布局。所有视觉元素都具有此属性。请参阅视觉树以查看代码示例。

由于与 uGUI 相比在布局上存在根本差异,对于 UI 元素的锚定和轴心,UI 工具包没有直接等效物。

元素的大小和位置由布局引擎控制。有关更多信息,请参阅布局引擎以及坐标和位置系统

渲染顺序

在 uGUI 中,层级结构中游戏对象的顺序决定了渲染顺序。层级结构中更靠后的对象最后渲染,并出现在顶部。在具有多个画布的场景中,根 Canvas 组件上的 Sort Order 决定了各个 UI 树的渲染顺序。

UI 工具包中视觉树中的渲染顺序以相同方式确定。父元素在其子项之前渲染,而子项按从第一个到最后一个的顺序渲染,以便最后一个出现在顶部。在具有多个 UI 文档的场景中,渲染顺序由根 UIDocument 组件上的 Sort Order 设置决定。

要在 UGUI 中更改元素的渲染顺序,例如使元素出现在顶部,您可以对游戏对象的 Transform 组件调用同级函数 (sibling function)。VisualElement 类提供了类似的函数来控制渲染顺序。由于所有 UI 工具包控件都派生自此类,因此所有控件都可以访问此函数。

下表显示了控制渲染顺序的 uGUI 函数和 UI 工具包的等效函数:

操作 uGUI UI 工具包
使元素渲染在所有其他同级元素之下 transform.SetAsFirstSibling(); myVisualElement.SendToBack();
使元素渲染在所有其他同级元素之上 transform.SetAsLastSibling(); myVisualElement.BringToFront();
手动控制元素相对于其同级元素的渲染顺序 transform.SetSiblingIndex(newIndex); myVisualElement.PlaceBehind(sibling);
myVisualElement.PlaceInFront(sibling);

事件

与 uGUI 中类似,用户在 UI 工具包的交互会触发事件。代码可以订阅以接收事件回调,例如按下按钮或移动滑动条。

在 uGUI 中,所有 UI 元素都基于 MonoBehaviour,并且可以在编辑器中公开它们的事件。这允许设置与其他游戏对象的逻辑,例如隐藏或显示其他 UI 元素,或指定回调函数。

uGUI Button OnClick Inspector
uGUI Button OnClick Inspector

在 UI 工具包中,逻辑和 UI 布局是分开存储的。回调无法直接在游戏对象上设置或存储在预制件中。必须在运行时设置所有回调,并通过脚本处理回调。

Button playButton = new Button("Play");
playButton.RegisterCallback<ClickEvent>(OnPlayButtonPressed);
...
private void OnPlayButtonPressed(ClickEvent evt)
{
  // Handle button press
}

UI 工具包中的事件分发系统与 uGUI 中的事件不同。根据事件类型,事件不仅会发送到目标 UI 控件,还会发送到所有父控件。

要了解更多相关信息,请参阅分发事件

在同一项目中使用 uGUI 和 UI 工具包

可以在同一个项目中使用 uGUI 和 UI 工具包。

在当前版本中,UI 工具包不支持 3D 世界空间选取和渲染。应使用 UI 工具包创建整个游戏菜单,并使用 uGUI 创建三维世界空间

还可以使用 uGUI 创建整个项目,并使用 UI 工具包仅创建某些菜单项。

您可以将 UI 工具包或 uGUI 用于任何不会在自身边界外交互的项。例如,对于运行时 UI,您可以使用 uGUI 创建屏幕按钮,例如移动端的游戏杆,并使用 UI 工具包创建模态窗口。

但是,混合 UI 之间的高级交互不起作用:

  • 您无法仅使用键盘在 UI 工具包中的焦点元素和 uGUI 选定对象之间自由导航。要导航,必须使用 C# 脚本在边界元素上注册事件,并手动选择或聚焦另一个域中的下一个元素。
  • 不能在 UI 工具包层级结构中嵌入 uGUI,也不能在 uGUI 层级结构中嵌入 UI 工具包。您可以使用 RenderTexture 进行绘制,但事件将无法赶上。
  • UI 工具包中的样式和事件约定与 uGUI 不同。如果使用分散的 uGUI 和 UI Tookit 组合,很难使项目具有统一的 UI。

其他资源

Migrate custom controls from an earlier version to Unity 6
从即时模式 GUI (IMGUI) 迁移到 UI 工具包