UI Element的简单介绍和基本使用

Unity - Manual: UXML elements reference (unity3d.com)

UIElement介绍

UIElement(现更名为UI ToolKit但是程序集名称还是UIElement)是Unity新推出的一种UI解决方案,目标是一站式解决Editor+Runtime的UI设计需求,使用C# + HTML的形式进行开发,其中HTML用以定义UI样式和内容,C#引用HTML定义内容+绑定数据,并且与GamePlay进行交互。

我们来看看他的底层是怎么样的:

UI Element的简单介绍和基本使用_第1张图片

  •  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视口操作(缩放,平移,更改分辨率)。

UIElement基础知识

  • 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中的后代选择器作用一致,最后> 表示取得类的某个子元素。三者可以灵活搭配使用。

RMGUI和IMGUI对比

上面提到UIElement使用RMGUI的模式,并且基于其做了按需更新的模式达到性能优化的效果,但目前Unity编辑器拓展主流仍然是Immediate Mode GUI (IMGUI)的形式,他不保存任何状态写起来非常爽快,但是问题就是需要每帧无差别的收集所有VB/IB然后进行绘制操作,相比RMGUI按需更新的模式就比较消耗性能。

创建一个简单的窗口程序

首先在Assets下创建一个名为Editor的文件夹,和编辑器有关的监本都要创建在这个文件夹下。然后在Editor文件夹下右键——Create——UIElement Editor Window,然后就会出现C#,UXML,USS三个文件。

C#

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorWindow : EditorWindow
{
    [MenuItem("Window/UIElements/TestEditorWindow")]
    public static void ShowExample()
    {
        TestEditorWindow wnd = GetWindow();
        wnd.titleContent = new GUIContent("TestEditorWindow");
    }

    public void OnEnable()
    {
        //创建根节点
        VisualElement root = rootVisualElement;
        
        //读取UXML
        var visualTree = AssetDatabase.LoadAssetAtPath("Assets/Editor/TestEditorWindow.uxml");
        
        //读取USS
        var styleSheet = AssetDatabase.LoadAssetAtPath("Assets/Editor/TestEditorWindow.uss");
        
        //创建新的子节点
        VisualElement labelFromUXML = visualTree.CloneTree();
        
        //为UXML添加USS样式
        labelFromUXML.styleSheets.Add(styleSheet);
        
        //将子节点添加到根节点
        root.Add(labelFromUXML);
    }
}

UXML



    

主要关注Label text这一行,指定了当前标签的文本内容。 

CSS

Label {
    font-size: 20px;
    -unity-font-style: bold;
    color: rgb(68, 138, 255);
}

css则指定了当前标签的具体样式。

UXML元素介绍

VisualElement

  • 这是所有视觉元素的基类
  • 在UnityEngine.UIElements命名空间下
  • 允许的子元素:任意数量的VisualElement

在上一章中我们就创建了VisualElement类型根节点,之后将子节点挂在该根节点上

BindadbleElement

  • 继承自VisualElement
  • 在UnityEngine.UIElements命名空间下
  • 允许的子元素:任意数量的VisualElement
  • 可以绑定到一个SerializedProperty上,属性的值和显示的值是同步的

常用元素

1.均在UnityEngine.UIElements命名空间下
2.无符号表示允许子元素数量是任意数量的VisualElement
3.X字符表示不允许有子元素
4.不作特殊说明,均包含所有VisualElement属性

Box

根据其内容绘制一个框

TextElement (X)

显示文本的元素

Label (X)

文本标签

  • 继承自TextElement

Image (X)

显示图像

IMGUIContainer (X)

绘制IMGUI内容的元素

  • focus-index 默认值是 0
  • focusable 默认值是 true

用法示例:

     
        
        
     


    viewElement.Q().onGUIHandler += OnDrawCustomGUI;

    private void OnDrawCustomGUI()
    {
        EditorGUILayout.BeginHorizontal();
        
        EditorGUILayout.LabelField("TestIMGUI");
        if (GUILayout.Button("Button"))
        {
            Debug.LogError("TestIMGUI");
        }

        EditorGUILayout.EndHorizontal();
    }



Foldout

通过一个toggle控制展开或收起

  • 继承属性 BindableElement

简单案例1

USS

.h
{
	height: 150px;
	background-image: resource("Assets/Editor/Sample1/unity.png");
}
.pic
{
	width :50px;
	height:50px;
	background-image: resource("Assets/Editor/Sample1/unity.png");
}

resource里面指定的是当前需要显示图片所在的位置

UXML




    
    	
    	
    		
    


C#侧的代码与之前一样,加载出对应的UXML和USS并应用。

结果

UI Element的简单介绍和基本使用_第2张图片

模板

1.Template (X)

通过对另一个UXML模板的引用,使用其Instance元素来实例化

  • name:此元素的字符串标识符
  • path:要加载的UXML文件的路径

2.Instance (X)

一个模板的实例

  • template:对Template实例化,命名为name

3.TemplateContainer (X)

模板容器

  • 继承属性 BindableElement
  • template:此模板的字符串标识符


简单案例2

 模板UXML定义为portrait.uxml



    
    	
    	
    

在另一个UXML使用时