搜索 Unity

Unity UI toolkit preview
Unity UI toolkit preview
分享

Is this article helpful for you?

Thank you for your feedback!

UI Toolkit是一款专为开发用户界面和编辑器扩展而制作的功能、资源和工具集合。曾作为UI Elements首次亮相的UI Toolkit为开发者们提供了一种采用保留模式(retained-mode)的UI框架,以辅助Unity扩展的定制UI开发。

在最新的Unity版本里,UI Toolkit从网页技术汲取了灵感,并带来了熟悉且直观的UI创作体验。本文将盘点工具各功能的特点,并分享几条用UI Toolkit创作、替代UGUI的技巧。

可以查看这篇手册内容来了解两种UI系统间的深入比较。

开始创作

Unity 2021 LTS目前已经开放下载与使用。该版本蕴含了整个Unity编辑器和底层基础功能一年多以来的工作结晶,以及Unity 2021.1和Unity 2021.2 Tech Stream版的特色功能(外加六个月的质量打磨)。

要想开始工作,请在Unity Hub里下载最新版的Unity。

Unity Hub login screen

使用流程

我们来了解下UI Toolkit究竟是怎样让工作更流畅的吧。 

与艺术家合作制作UI可以是一项非常复杂的任务。当艺术家在画布上泼洒颜料、添加材质时,程序员则需要创建脚本、行为和OnClick监听程序。随后,双方在合并工作成果时,有可能会出现合并冲突,并出现不少需要快速解决的问题。

UI Toolkit支持让美术人员编辑UXML和USS文件,由C#处理所有的逻辑,防止出现合并冲突。比如,按钮可以只用C#处理,脚本会按名称查询按钮并应用逻辑,不需要程序员编辑任何UXML或USS文件。

这个流程不仅能缓解合并冲突,而且还能简化未来的风格改动。如果你需要修改项目的字体,你不必一个个地检查每个资产并编辑文本。这就避免了过于繁琐的工作带来的“看走眼”问题——而越大的游戏工作起来就越复杂。

UI Toolkit的Panel Settings包含了所有的文本设置。因此,要想改变某个UI Document下的字体,你只需要编辑那些Panel Settings即可。尽管编辑器脚本同样可以辅助UGUI创作,但UI Toolkit框架可以自动化这一流程。

Visual Element是编辑按钮、图像、文本等每一种UI Toolkit元素的基础类。你可以将它视作是UI Toolkit版的GameObject。同时,UI BuilderWindow > UI Toolkit > UI Builder)是一款无需代码即可创建、编辑UI的可视化工具。这对艺术家和设计师来说都非常实用,他们可以随时查看UI的制作过程。

作为一款为熟悉网页开发的开发者而准备的工具,UI Toolkit可以分离UI的逻辑和视觉风格从而重新定义工作的组织方式、避免文件冲突,从而改善美术人员与程序员之间的协作。UI Builder负责UI元素的位置、风格和设计,而C#代码可以单独请求所需要的UXML文件再应用逻辑。

开始使用UXML

UXML文件可与HTML网页文件相媲美。它们代表了视觉元素,包含了UI的层级结构。请打开Assets > Create > UI Toolkit > UI Document来创建UXML文件。然后使用UI Builder可视化并编辑UXML。

注意,UXML文件和GameObject不同,而是视觉元素的树状结构。要想精简层级结构、在一个单一的UI文档上加载所有的UXML元素。你可以在Windows > UI Toolkit > Debugger下打开UI Toolkit Debugger来可视化UI。

 

要想开始工作,你可以在Windows > UI Toolkit > Samples下查看UXML Element的例子

UI Builder还支持直接创建、可视化和测试UXML文件,不必启动游戏。你只需从UI Builder Library 面板拖入UI控件(标准或自定义)到层级结构中,并组合多个UXML文件来创建最终的UI。

假设我们的用户界面由三个元素组成:

  • 血量
  • 分数
  • “你赢了”弹窗

“你赢了”窗口将显示血量、分数以及重新开始按钮。

每种元素会在另一个UI面板中被使用,它们包含在几个单独的UML文件里,组合而成popup.uxml——文件包括了health.uxml、score.uxml外加Restart按钮。因此,管理分数和血量的代码逻辑(score.cs和health.cs)是独立于层级结构的。这意味着health.cs会一直更新health.uxml的数值,无论UI是单独显示在屏幕上还是在另一个弹窗内。

结合UXML也可以促进编辑对象的可视化。通过打开Class List 选项 ,在UI Builder层级结构 ,你可以在第一时间看到什么在影响着对象,并使用选择器(selector)来保持风格的有序性。

另一个好处是关于场景层级结构 。UI Toolkit不需要一张包含几十个GameObject的Canvas,而只需要一份与UI Document相关联的UXML文件。

vs

这种工作流程对大型团队特别有利。每位团队成员都可以在自己的UXML文件上工作,然后将文件添加到场景的UI Document中,而不必几个人在同一个场景内工作,并招致可能的合并问题。

Panel Settings(面板设置)

Panel Settings Asset配置文件(Assets > Create > UI Toolkit > Panel Settings Asset)确定了UXML在游戏中的实例化与显示方式。一个项目可以有多个Panel Settings Asset,让游戏的UI能应用多种不同的风格。比如,你可以为HUD应用一种面板设置,为Minimap(小地图)应用另一种设置,两者间的区别较大、使用需求也不同。

Panel Settings可被看作是UGUI Canvas与Canvas Scaler的结合体,外加文本设置等选项,让面板内的所有文本都能使用相同的基础设置。这就避免了花费大量时间手动设置每一种字体。当然,每种字体设置仍可以根据需要在UI Document中被改写。

事件

UI Builder和UXML文档并不能用于管理事件。要想处理按钮点击或任何其他事件,你可以创建一个C#脚本并将其关联到UXML。

public class UIEventHandler : MonoBehaviour
{
   [SerializeField]
   private UIDocument m_UIDocument;
 
   private Label m_Label;
   private int m_ButtonClickCount = 0;
   private Toggle m_Toggle;
   private Button m_Button;
 
   public void Start()
   {
       var rootElement = m_UIDocument.rootVisualElement;
 
       // This searches for the VisualElement Button named “EventButton”
       // rootElement.Query<> and rootElement.Q<> can both be used
       m_Button = rootElement.Q<Button>("EventButton");
 
       // Elements with no values like Buttons can register callBacks
// with clickable.clicked
       m_Button.clickable.clicked += OnButtonClicked;
 
       // This searches for the VisualElement Toggle named “ColorToggle”
       m_Toggle = rootElement.Query<Toggle>("ColorToggle");
 
       // Elements with changing values: toggle, TextField, etc... 
// implement the INotifyValueChanged interface,
       // meaning they use RegisterValueChangedCallback and 
// UnRegisterValueChangedCallback
       m_Toggle.RegisterValueChangedCallback(OnToggleValueChanged);
 
       // Cache the reference to the Label since we will access it repeatedly.
       // This avoids the relatively costly VisualElement search each time we update
       // the label.
       m_Label = rootElement.Q<Label>("IncrementLabel");
       m_Label.text = m_ButtonClickCount.ToString();
   }
 
   private void OnDestroy()
   {
       m_Button.clickable.clicked -= OnClicked;
       m_Toggle.UnregisterValueChangedCallback(OnToggleValueChanged);
   }
 
   private void OnButtonClicked()
   {
       m_ButtonClickCount++;
       m_Label.text = m_ButtonClickCount.ToString();
   }
 
   private void OnToggleValueChanged(ChangeEvent<bool> evt)
   {
       Debug.Log("New toggle value is: " + evt.newValue);
   }
}

摆放

视觉元素的摆放默认采用Flexbox架构。它可以保证大多数UI布局能自动适应容器或屏幕尺寸。你可以将其应用于包含两个及以上元素的Visual Element Tree,定义每种元素在树形结构上的对齐方式。

将一个元素放在Absolute(绝对)位置会将其放置在相对于父对象的位置,不会影响其他元素或被其他元素所影响。

对于Flex(灵活)与Align (对齐)设置,你可以参考以下简单的层级结构:

你可以使用UI Builder Inspector编辑以下设置:

  • Basic:表示着某个元素的默认尺寸,在任意Shink(在父对象没有剩余空间时减小比例)或Grow(在父对象有剩余空间时增大比例)操作发生之前。
  • Direction (Row and Column):用于创建类似于UGUI的Vertical Layout Group和Horizontal Layout Group结构。
Table Vertical Layout
  • Wrap:检查元素是否需要换行,是将其摆放在上一元素的前边或后边。
Table illustrating wrap
  • Align Items:以元素的最小尺寸摆放到选定位置。
Item alignment options
  • Justify Content:确定主轴上各元素之间的间距。
Elements spacing options

请在UI Toolkit Layout Engine文档中了解更多关于视觉元素摆放的信息。

样式设计

样式设计是UI Toolkit施展全部能力的地方。为视觉元素添加Style(风格)由USS文件 (Assets > Create > UI Toolkit > StyleSheet) 完成。它们相当于Unity的网页CSS文件,采用了相同的基于规则的格式。

注意,UI制作并不一定需要自定义USS文件。UI Toolkit默认提供有运行时和编辑器样式,但你可以通过自定义USS来扩展默认样式,或者从零开始创建自己的样式。

你可以在UI Builder Inspector StyleSheet 面板中添加Style选择器,然后用代码或UI Builder进行编辑。

UI Builder的USS Style选择器

在检视器内匹配脚本类

在上方截图中,.RedButton选择器被添加到一个按钮上。选择器将于所有按钮自动包含的内置.unity-text-element.unity-button class一起出现。

下方例子中的USS规则将所有包含.RedButton类的元素的背景颜色设置为了红色。规则的第一行是一个按类名进行选择的选择器,后接几种需要应用的样式。

.RedButton { background-color: red; }

类似CSS,脚本类可以组合起来限制规则选择器的范围:

.RedButton.BlueText { color: blue; }

在例子中,只有同时具备.RedButton和.BlueText 类的对象才会有蓝色的文本。当其与前边的代码片段相结合,则按钮的背景也会变为红色。

像CSS样式一样,USS文件可以根据对象的状态来改变外观:

.unity-button:hover { background-color: red; }

在例子中,按钮在有鼠标悬停时其背景会变为红色。你可以通过点击UI Builder 工具栏Preview按钮来预览鼠标悬停效果。

深度式例

在了解了UI Toolkit的基本功能后,我们再通过一个例子来比较下UGUI与UI Toolkit的不同。我们的目标是创建一个简单的菜单,它在鼠标悬停时会产生以下两种效果:

  • 改变按钮的背景颜色
  • 改变按钮的文本颜色

在使用UGUI创建时,我们需要设置如下层级结构:

我们还得为部分对象添加额外的组件:

  • Menu要有一张背景图像,要固定在一定位置以便对齐。
  • Buttons必须正确地锚定、对齐。
  • RestartQuit按钮需要:
    • 一个能在鼠标悬停时动态地改变文本颜色的脚本。
    • 用于修改背景颜色的按钮组件设置(在编辑器中编辑)。

在本例中,Quit是一个红色按钮预制件。

现在,要想用UI Builder来创建菜单,我们首先要创建一个类似的层级结构:

Popup Align设置为Center,再将Buttons Flex Direction设置为Row,此时UI Toolkit弹窗看起来会像这样:

可以看到Quit按钮是红色的,它继承自QuitButton.uxml组件,该组件相当于一个按钮预制件。

要想真正看到UI工具包的神奇之处,你可以添加一个包含多条规则的PopupStyle.uss,随后...

.background {
   background-image: url('/Assets/Assets/OptionsMenu.png#OptionsMenu');
   width: 500px;
   height: 300px;
}
 
.title {
   font-size: 32px;
   color: rgb(255, 255, 255);
}
 
.unity-base-field__input {
   background-color: rgba(0, 0, 0, 0);
   background-image: url('/Assets/Assets/OptionsMenu9Slice.png#OptionsMenu9Slice_2');
   width: 300px;
   height: 75px;
   font-size: 20px;
   color: rgba(255, 255, 255, 0.5);
   -unity-text-align: middle-center;
}
 
.unity-button {
   color: white;
   background-color: rgba(0, 0, 0, 0);
   background-image: url('/Assets/Assets/StartMenu.png#StartMenu_ButtonDefault');
   width: 160px;
   height: 30px;
   -unity-slice-bottom: 1;
}
 
.unity-button:hover {
   color: rgb(0, 21, 255);
}
 
#Restart {
   -unity-background-image-tint-color: rgb(112, 202, 125);
}

注意,选择器有优先级。直接写进UXML的样式将覆盖USS文件中的样式。这里,元素的宽高会被写到PopupStyle.uss中,但我们也可以直接在UI Builder中进行编辑并覆盖PopupStyle.uss文件。详细的优先级规则可以在此处找到。

假设我们想改变菜单内的所有颜色,又不想修改游戏的其他部分,如果在UGUI里我们就需要一次一个地手动编辑所有组件的颜色。但在这个例子中则不同。尽管只存在一个Quit按钮的预制件,但我们可以把所有按钮都做成预制件,随后一次性覆盖所有实例的设置。接着,在经过手动修改后,菜单中的颜色会无视所有预制件上的颜色修改。

有了UI Toolkit,我们只需在新建的NewStyle.uss里复制PopupStyle.uss标签,再用NewStyle.uss替换掉PopupStyle.uss即可。

在场景中添加UI

在创建和编辑完UXML文件之后,最后一步是将其添加到实际场景中。为此,我们需要替换掉Scene Canvas 元素,并创建一个带有UI Document 元素空GameObject。在该元素中添加popup.uxmlPanel Settings 文件,然后点击Play来测试你的UI。

现在就来试用UI Toolkit吧

如果你决定尝试UI Toolkit,我们欢迎你前来UI论坛留下你的想法,或在官方文档中了解更多的细节。

最后,你可以在最新的Unity Platform Roadmap了解到最新的更新。或直接向产品团队进行反馈——我们期待着您的意见!

本文由Accelerate Solutions团队的Marina Joffrineau撰写,该团队由Unity最资深的开发者们组成,专为各种规模的游戏工作室提供咨询和定制开发方案服务。要想进一步了解Unity Accelerate Solutions以及我们如何帮助用户达成目标,请访问我们的网站

2022年4月20日 类别 Engine & platform | 20 分 阅读

Is this article helpful for you?

Thank you for your feedback!