UIElements是Unity全新的保留模式UI框架,面向Unity 2019.1作为公开API发布。现在UIElements是一款可以轻松扩展Unity编辑器的工具,未来版本将加入游戏内支持和可视化制作功能。
你可以下载UIElements示例项目进行学习:
https://github.com/Unity-Technologies/UIElementsUniteLATurretDemo
UIElements介绍
过去,在Unity中构建自定义编辑器窗口和检视窗口意味着要使用即时模式API:IMGUI。
IMGUI可以帮助你轻松的构建用户界面,但是在构建较复杂的应用程序时会很难扩展。系统也很难优化渲染过程,因为用户可以随时在某一帧内大幅修改UI结构。
IMGUI的所有UI都通过C#代码声明,这意味着未来可视化制作UI的工具都会生成C#代码,这种做法很复杂。
UIElements作为保留模式API,它的核心思想是:用户构建出自己的UI对象层级,然后让系统进行渲染。通过这种方式,该系统可以优化绘制的内容和时间,从而实现更好的整体性能。
这种范例也允许用户把层级和样式从功能中分离,从而更好地分开关注点,为艺术家和程序员提供更易于理解的UI制作过程。
保留模式
UIElements的基本构造部分是VisualElement类,所有元素都是VisualElement或从中继承。独立的VisualElement可以互相嵌套,以形成UI层级。布局,样式和其它系统会遍历该层级,以便正确地渲染UI到屏幕上。
在编辑器中,每个EditorWindow都有一个rootVisualElement属性,该属性表示层级的顶部VisualElement。Element元素需要作为子对象添加到根对象上,从而让系统知道元素的信息,并进行绘制。
using UnityEditor; using UnityEngine.UIElements; public class ExampleWindow : EditorWindow { public void OnEnable() { var root = this.rootVisualElement; IntSlider slider = new IntSlider(); root.Add(slider); // 添加滑块为根对象的子对象 } }
只要元素处于层级之中,它会继续绘制,更新和消耗用户事件,而无需开发人员的输入。这就是保留模式和即时模式最大的不同之处,开发人员只需声明应该发生的事情和发生时间,不需要管理帧和帧之间的渲染。
为了停止绘制某个元素,例如这里的滑块,开发人员既可以通过样式变更,使它暂时无法看到,也可以把它从层级中永久移除。
// 轻松而动态地隐藏和显示元素 slider.style.display = Display.None; // 该元素的工作已经完成,可以移除它了 slider.RemoveFromHierarchy();
保留模式也可以使用文档模型,让开发者分离层级(使用UXML)和样式(USS)声明为单独的资源。在C#代码中,你可以使用内置查询系统和事件系统,仅专注于绑定声明的UI和功能及数据。
通过为层级和样式使用分离的资源,可以可视化制作UI,可让所有用户在Unity中轻松调整、制作和设计UI。
可重用模板UXML
你可以完全使用C#代码组合元素层级,但和样式一样,大多数层级不会在UI的生命周期内有太大变化。因此建议模块化处理UI,定义层级为基于XML的独立资源,即UXML。
<UXML xmlns="UnityEngine.UIElements"> <VisualElement name="the-container"> <Label /> <SliderInt low-value="0" high-value="100" /> </VisualElement> </UXML>
标签名称对应着C#类型,完全支持继承自VisualElement的用户定义类型。属性会在创建时在新元素上设置,嵌套的标签会成为父标签的子标签。
你可以像其它Unity资源一样加载.uxml资源,在过程中构造VisualTreeAsset对象,然后根据需要在任意元素下实例化或克隆VisualTreeAsset。
var uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/ExampleUI.uxml"); uxml.CloneTree(root); //在uxml中创建标签为根部分的子部分
下面将介绍如何使用查询系统通过UXML获取刚创建的元素。
共享样式USS
通过C#的属性可以直接在VisualElements上设置样式。虽然大部分样式会静态定义的,但它也可以在C#代码中分离描述和UI逻辑。
UIElements使用Unity专用的StyleSheet资源,称为USS,它使用CSS标准的子集。你可以使用和CSS代码相同的选择器,以识别哪些元素应该得到什么样式,样式本身是键值对。
/* 按照样式类 */ .standard-label { padding: 6px; } /* 按照元素名称 */ #the-label { font-size: 60px; } /* 按照C#类型 */ Label { color: rgb(68, 255, 93); }
你可以像其它Unity资源一样加载.uss资源,在过程中构造StyleSheet对象,然后指定它到所需的元素,它会自动应用其中的样式到该元素及其子元素上。
var uss = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/ExampleUI.uss"); root.styleSheets.Add(uss);
虽然样式可以根据名称属性或C#类型来应用,但为了更好的样式重用效果,你可以给元素指定一个或多个样式类,根据这些类在USS资源匹配样式,你可以把这些样式视为标签。
<!-- Assign a style class in UXML: --> <Label /> // 在C#指定样式类 var label = new Label(); label.AddToClassList("blue-label");
你可以添加多个StyleSheets到相同元素,使用多个规则来匹配相同的元素。使用USS来设置复杂的重写规则,同时尽可能重复使用样式。
这样对共享样式进行迭代变成了很简单的事情,因为我们不必等待C#代码进行重新编译。StyleSheet(USS)资源的改动会在文件保存时自动应用到编辑器。
UQuery
UIElements中的查询系统叫UQuery,它和Web上的jQuery类似,允许你使用名称属性,当前指定的样式类列表和C#类型的组合来查找层级中的元素。
// 通过样式类和类型 var label = root.Q<Label>(className: "blue-label"); // 通过名称(它会返回VisualElement) var container = root.Q("the-container");
你还可以创建Query对象以实现优化的重用效果,此时需要对动态层级多次运行查询过程。
// 构建一次查询 UQueryBuilder<SliderInt> query = root.Query<SliderInt>(classes: "blue-slider"); // 多次运行以获取更新结果 query.ForEach(slider => Debug.Log(slider.name));
事件
UIElements提供了一个事件系统。事件通常会发送到特定元素,然后在UI树的上下传播,直到使用完所有事件,但传播行为是可以定制的。
MouseMoveEvent等基本事件会由系统发送,你可以进行注册以接收事件,也可以定义和发送自定义用户事件。Event事件是了解UI中的状态何时变化或用户何时执行操作的主要方法。
下面的示例会检测用户何时改动滑块数值,然后在标签元素显示新的数值。
var label = new Label(); var slider = new SliderInt(); slider.RegisterCallback< ChangeEvent<int>>(evt => { display.text = evt.newValue.ToString(); });
UIElements Debugger
如果UI出现问题,或是如果没有看到应该出现在屏幕的元素,你可以使用UIElements Debugger,该工具类似Chrome和Firefox里的网页调试工具。
使用UIElements Debugger调试UI的元素,可以启用Pick功能,把鼠标移动到元素上,或是右键单击元素并选择Inspect。UIElements Debugger会在左侧面板显示当前窗口的完整实时层级,在右侧面板显示样式检视窗口。
在样式检视窗口中,你可以查看什么样式指定到某个元素上,以及每个样式值来自什么地方,即在哪个StyleSheet资源和哪个选取器内。
最后,你可以实时添加和编辑样式值,在UI查看它们的效果。
其它功能
Bindings绑定
许多控制功能可以绑定到SerializedObjects,以链接UI和资源数据。任何实现IBindableinterface的元素,例如:所有内置字段都可以接收SerializedProperty的字符串绑定路径。然后你可以把元素层级通过 Bind()绑定到SerializedObjects。
IMGUIContainer
如果有许多使用IMGUI编写的编辑器UI,你可以使用特别的IMGUIContainer元素在UIElements UI中作为另一元素嵌入IMGUI UI。IMGUIContainer会获取用作OnGUI( )循环的回调,和正常情况一样从外部接收所有事件。
Scheduler调度工具
UIElements提供了一个简单的内置调度工具,你可以使用调度工具按一定时间延迟回调,然后以设定的间隔重复执行回调。
未来展望
我们正在开发UIElements对游戏内UI 的支持。此外,我们计划为UIElements提供可视化工作流程,让用户可以通过少量C#代码,甚至不使用C#代码来设计和构造可用的UI。
与此同时,Unity上越来越多的部分将使用UIElements构建,包括检视窗口,使用专用编辑器窗口的新工具和新工具栏。
我们会继续维护和改进IMGUI和UGUI,我们目前没有弃用它们的计划。尽管如此,UIElements将成为得到最多支持的推荐方法,用于在Unity构造UI,UIElements从Unity 2019.1开始在编辑器内使用。
更多Unity最新功能分享与技术讨论,尽在Unity Connect平台(Connect.unity.com)。下载Unity Connect APP,请点击此处。
本文转自:微信号 - Unity官方平台(Unity-GreaterChina),转载此文目的在于传递更多信息,版权归原作者所有。