我关注类似MVVM的UI框架已经很久了,从2019.1发布的功能列表中我终于看到了非常想要的功能库。那就是UI Elements.
我在2016年也写过类似框架介绍,感兴趣的话可以看一下细说PreGUI框架设计思路-蛮牛网
与PreGUI的设计思路类似,但是官方出品质量肯定上去不止一个台阶。另外配有完善的Profile工具。让你可以清楚的看到UI的布局细节。
截止到今日,IMGUI还是作为辅助UI系统在Unity中使用【编辑器】,相信过不了多久他就会转正甚至取代目前的UGUI,所以我们现在早点了解也好未来可以快速上手。好了下面开始正文 :)

使用 UI Elements Debugger 查看已有Editor的结构

你甚至可以在Elements Debugger中实时的修改属性值

Case01

这里就不上图了。简单描述下 rootVisualElement,他就是我们所有UI的根节点。如果你写过HTML 那么你肯定可以轻易地的
可以轻易地的过渡到现在的写法上,理解上亦是如此。

但下面的代码里,代码我们先获取到了UI的根节点,跟然后创建各种元素,将其添加进我们的根节点上。至此我们不需要加上额外代码,即可渲染控件,就如同我们在运行时里使用UGUI做的一样。

这里有一个小技巧,像HTML一样我们可以通过ID来寻找我们的控件。所以在创建组件的同时,如果考虑到我们后续需要去动态寻找该组件,那么我们将其设置一个name,并且通过name来寻找。就像下面做的这样。var lable =rootVisualElement.Q

⚠️注意:.Q 查询函数为所有visual elements的扩展函数,也就意味着所有的元素都能搜索自己结构下的节点。

在这里你可以给控件添加回调函数,在该函数中你甚至可以获取触发当前回调的来源(每个控件都有callback)。就像下面做这样var slider = evt.target as SliderInt;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void OnEnable()
{
var root = rootVisualElement;
//创建lable
var label = new Label();
label.name = "lable01";
//创建slider
var slider = new SliderInt();
slider.name = "slider01";
slider.RegisterValueChangedCallback(SliderValueChangeCallback);
root.Add(slider);
root.Add(label);
}
private void SliderValueChangeCallback(ChangeEvent<int> evt)
{
var slider = evt.target as SliderInt;
var lable =rootVisualElement.Q<Label>("lable01");
lable.text = evt.newValue + " << fontsize is change. slider name:" + slider.name;
lable.style.fontSize = slider.value;
}

Case02

看图~

在这里,你可以看到目前所有可以用的控件

Case03

当然我们想要的更多,你同样可以通过样式文件与布局文件来渲染窗口。这才是我们最终的目的,什么让我们来看一下范例吧。

创建布局与样式

读取uxml与uss

⚠️注意:我们读取之后的类型分别为 VisualTreeAsset 与 StyleSheet 。

读取之后直接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
VisualElement m_RootElement;
VisualTreeAsset m_ModulesVisualTree;
public void OnEnable()
{
m_TurretBuilder = new TurretBuilder(this);
// Hierarchy
m_RootElement = new VisualElement();
m_ModulesVisualTree =
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
"Assets/Demo/UI/TurretEditorTemplate.uxml");
// Styles
var stylesheet =
AssetDatabase.LoadAssetAtPath<StyleSheet>(
"Assets/Demo/UI/TurretEditorStyles.uss");
m_RootElement.styleSheets.Add(stylesheet);
// WILL BE FIXED: Unset padding on parent InspectorElement.
m_RootElement.RegisterCallback<AttachToPanelEvent>(OnRootAttachToPanel);
}

创建Elements

使用CloneTree API可以创建读取出来的结构。并且将当前节点作为root的子节点。

1
m_ModulesVisualTree.CloneTree(root);

事件绑定

暂时我没有找到事件映射或者绑定的代码。也有可能是这部分的API没有开放出来。暂时来看IMGUI的完善进度也比较快,就算现在没有事件映射,也可以等等。毕竟现在还没有过preview阶段。不过现在已经看起来像那么一回事了,相信用上它的一天很快会到的。

Case4

添加高亮与提示(提示有限并不能很好的支持)

在编辑uxml与uss的时候你需要一个代码高亮。在rider里是这样设置的