Unity UIElement实践总结
前言
Unity的UIElement已经发布两年多了,最近才开始正式重度与其打交道,此文章主要介绍UIElement和一些常用功能和一些不常见的坑,并且提供一些UIElement的学习资料。
正文
UIElement介绍
UIElement(现更名为UI ToolKit但是程序集名称还是UIElement,雀食没话说)是Unity新推出的一种UI解决方案,目标是一站式解决Editor+Runtime的UI设计需求,使用C# + HTML的形式进行开发,其中HTML用以定义UI样式和内容,C#引用HTML定义内容+绑定数据,并且与GamePlay进行交互。
我们来看看他的底层是怎么样的:
- UIElement使用了名为UIElements Renderer(UIR)的渲染后台,为UIElement渲染量身定制,尽可能提高性能。
- 使用Retained Mode GUI (RMGUI)以及按需更新的模式,当UI元素没有发生变化的时候几乎0消耗。
- 渲染时分配一个
大的VB/IB缓冲区
,使用特制的Uber Shader,减少渲染状态切换,一个DrawCall即可完成整个UIElements的绘制(即使UI元素发生变化,也会将发生变化的UI元素的VB/IB放入一开始分配的那个大的VB/IB缓冲区)。 - 性能优化,把更多的工作下放到GPU去做,减少CPU开销,例如UI元素的属性会被存储在GPU内存上,GPU加速Clip,DynamicTransform(GPU加速UI元素的平移,缩放,旋转操作),GPU加速UI视口操作(缩放,平移,更改分辨率)。
此部分更多内容参见:Built for performance: the UIElements Renderer – Unite Copenhagen 2019
- UXML是UI元素的布局文件,比如一个按钮其中包含背景图片和文字,可通过
VisualTreeAsset.CloneTree(VisualElement);
形式实例化出来 - USS是UI元素的样式文件,比如一个按钮其中包含背景图片和文字具体的内容和样式,可通过
VisualElement.styleSheets.Add(StyleSheet);
的形式将其样式应用到VisualElement上,也可以通过VisualElement.AddToClassList(XXX)
来将其中某一个样式应用给VisualElement - USS中的三个特殊字符:
.
,#
,space(注意这是一个空格)
和>
,也就是 CSS中的选择器 ,但在USS中有些许不同,其中.
用于引用和描述UXML中已有的Class样式,而#
则是在USS中新声明的一个Class,可以直接通过new VisualElement{ name = "XXX" };
的形式实例化一个VisualElement,空格和CSS中的后代选择器作用一致,最后>
表示取得类的某个子元素。三者可以灵活搭配使用。
实用功能
基于VisualElement创建一个拖拽区域
关键字为IDropTarget和IDragTarget,前者为可被放置区域,后者为可以被拖动的区域,下面是个示例
1 | public class DecorateNodeDropDownArea : Box, IDropTarget |
隐蔽的坑
VisualElement的layout宽高NAN(无限大)
发生这种情况是因为VisualElement的一些信息刷新不是实时的,比如你在当前帧创建了一个VisualElement,并为它设置了位置和大小,但是他可能下一帧,甚至更远的未来才会正式应用你设置的位置,在此之前你获取到的内容都是非法的
解决方式有三个
- 手动判断宽高(VisualElement.layout)是否为NAN
- 通过schedule来延迟调用(VisualElement.schedule)
- 逻辑层自己封装一个Transform
VisualElement selection丢失
焦点丢失就会导致selection丢失
在UI Builder中的布局和在EditorWindow中的布局不一致
因为Unity自作聪明塞得个TemplateContainer导致的一系列问题
解决方法:
1 | // 获取EditorWindow的Root |
参考
从零开始学习UIElement(非常适合没有了解过UIElement的人)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 登峰造极者,殊途亦同归。!
评论