| 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视口操作(缩放,平移,更改分辨率)。
 UIElement基础知识UXML是UI元素的布局文件,比如一个按钮其中包含背景图片和文字,可通过 VisualTreeAsset.CloneTree(VisualElement);形式实例化出来USS是UI元素的样式文件,比如一个按钮其中包含背景图片和文字具体的内容和样式,可通过 VisualElement.styleSheets.Add(StyleSheet);的形式将其样式应用到VisualElement上,也可以通过 VisualElement.AddToClassList(XXX) 来将其中某一个样式应用给VisualElementUSS中的三个特殊字符:.,#,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<TestEditorWindow>();
        wnd.titleContent = new GUIContent("TestEditorWindow");
    }
    public void OnEnable()
    {
        //创建根节点
        VisualElement root = rootVisualElement;
        
        //读取UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/TestEditorWindow.uxml");
        
        //读取USS
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/TestEditorWindow.uss");
        
        //创建新的子节点
        VisualElement labelFromUXML = visualTree.CloneTree();
        
        //为UXML添加USS样式
        labelFromUXML.styleSheets.Add(styleSheet);
        
        //将子节点添加到根节点
        root.Add(labelFromUXML);
    }
}
 UXML  
 <?xml version="1.0" encoding="utf-8"?>
<engine:UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:engine="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
>
    <engine:Label text="Hello World! From UXML" />
</engine: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)文本标签 Image (X)显示图像 IMGUIContainer (X)绘制IMGUI内容的元素 focus-index 默认值是 0focusable 默认值是 true
 用法示例:  
      <VisualElement class="container">
        <IMGUIContainer>
        </IMGUIContainer>
     </VisualElement>
    viewElement.Q<IMGUIContainer>().onGUIHandler += OnDrawCustomGUI;
    private void OnDrawCustomGUI()
    {
        EditorGUILayout.BeginHorizontal();
        
        EditorGUILayout.LabelField("TestIMGUI");
        if (GUILayout.Button("Button"))
        {
            Debug.LogError("TestIMGUI");
        }
        EditorGUILayout.EndHorizontal();
    }
 
 Foldout
通过一个toggle控制展开或收起 简单案例1USS  
 .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  
 <?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
    <Box class ="h">
    	<Image class="pic"/>
    	<Foldout>
    		<Label text="Label"/>
    		<TextElement text ="TextElement"/>
        </Foldout>
    </Box>
</UXML>
 C#侧的代码与之前一样,加载出对应的UXML和USS并应用。 结果  ?
 模板1.Template (X) 通过对另一个UXML模板的引用,使用其Instance元素来实例化 name:此元素的字符串标识符path:要加载的UXML文件的路径
 2.Instance (X) 一个模板的实例 template:对Template实例化,命名为name
 3.TemplateContainer (X) 模板容器 继承属性 BindableElementtemplate:此模板的字符串标识符
 简单案例2
?模板UXML定义为portrait.uxml  
 <?xml version="1.0" encoding="utf-8"?>
<engine:UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:engine="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
>
    <engine:VisualElement class="portrait">
    	<engine:Label name="nameLabel" text="Name"/>
    	<engine:Label name="levelLabel" text="42"/>
    </engine:VisualElement>
</engine:UXML>
 在另一个UXML使用时  
 <?xml version="1.0" encoding="utf-8"?>
<engine:UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:engine="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd"
>  
  
<!--加载一个模板 需要路径(path) 和字符串标识符(name)-->
<Template path="Assets/Editor/Sample2/portrait.uxml" name="Portrait"/>
<engine:VisualElement name="players">
	<!--实例化该模板 并命名-->
	<engine:Instance template="Portrait" name="player1"/>
	<engine:Instance template="Portrait" name="player2"/>
	<engine:Instance template="Portrait" name="player3"/>
</engine:VisualElement>
</engine:UXML>
 C#侧的代码去掉了之前加载USS部分的代码。 结果  ?
 ?此功能可以用在一些较为常用的通用功能绘制等部分,避免大量冗余代码,后续的使用只需要实例化模板部分即可。 BaseField< T >(X)所有字段的抽象基类 继承属性 BindableElementfocus-index 默认值是 0focusable 默认值是 truelabel:与字段关联的文本
 BaseFieldTraits<ValueType, UxmlType>(X)继承自 BaseField< ValueType >value:字段的初值,类型为 ValueType
 Button(X)标准按钮 RepeatButton(X)按下时反复执行操作的按钮 继承自TextElementdelay:执行操作之前的初始延迟(以毫秒为单位); 默认值是0interval:每个动作重复之间的间隔(以毫秒为单位); 默认值是0
 Toggle(X)开关(复选框) 继承自 BaseFieldTraits<bool, UxmlBoolAttributeDescription>text :开关右侧的标签
 Scroller(X)滚动条 继承自VisualElementlow-value:滚动条的最小值high-value:滚动条的最大值direction:Horizontal或Vertical; 默认是Verticalvalue:滚动条的位置
 Slider (X)滑动条 继承自BaseFieldTraits<float, UxmlFloatAttributeDescription>low-value:滚动条的最小值high-value:滚动条的最大值direction:Horizontal或Vertical; 默认是Horizontalpage-size:滑块的页面大小
 SliderInt (X)Int类型的滑动条 继承自BaseFieldTraits<float, UxmlIntAttributeDescription>low-value:滚动条的最小值high-value:滚动条的最大值direction:Horizontal或Vertical; 默认是Horizontalpage-size:滑块的页面大小
 MinMaxSlider (X)允许用户指定最小值和最大值的滑块 继承自BaseFieldlow-limit:滚动条的最小值high-limit:滚动条的最大值min-value:滑块光标的最小值max-value:滑块光标的最大值
 EnumField (X)一个只能获取底层字符串值的字段Enum 继承自BaseField< Enum >type:必需,表示底层的C#类型的字符串 Enumvalue:表示字段值的字符串
 MaskField (X)多选菜单 在UnityEditor.UIElements命名空间下继承自BaseField< int >choices:逗号分隔的列表,最多包含32个选项,以显示在弹出菜单中value:一个整数,表示字段的值为32位掩码
 LayerField (X)图层单选菜单 在UnityEditor.UIElements命名空间下继承自BaseField< int >value:表示选定图层编号
 LayerMaskField (X)图层多选菜单 在UnityEditor.UIElements命名空间下继承自MaskField
 TagField (X)标签单选菜单 在UnityEditor.UIElements命名空间下继承自BaseField< string >value:表示Tag值的字符串
 ProgressBar (X)进度条 在UnityEditor.UIElements命名空间下继承自BindableElementlow-value:表示进度条最低值的浮点数(默认值为0)high-value:表示进度条最高值的浮点数(默认值为100)title:表示进度条标题的字符串
 简单案例3USS  
 .btn
{
	width :100px;
	height:30px;
}
.scr
{
	height:200px;
}
.sliH
{
	width:100px;
}
.sliV
{
	height:100px;
}
.efi
{
	width:100px;
	height:15px;
}
 UXML  
 <?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
  <Button class="btn" text ="Button"/>
  <RepeatButton class="btn" text ="RepeatButton" delay ="1000" interval="1000"/>
  <Toggle text="toggle"/>
  <Scroller class="scr" low-value="0" high-value="400" direction="Vertical" value="0"/>
  <Slider class="sliH" low-value="0" high-value="200" direction="Horizontal" page-size="1"/>
  <SliderInt class="sliV" low-value="0" high-value="200" direction="Vertical" page-size="1"/>
  <MinMaxSlider class="sliH" low-value="0" high-value="200" min-value="0" max-value="200"/>
  <!--<editor:EnumField class="efi" type="EnumTest" value="0"/>-->
  <editor:MaskField class="efi" choices="one,two,three,four" value="0"/>
  <editor:LayerField class="efi"/>
  <editor:LayerMaskField class="efi"/>
  <editor:TagField class="efi"/>
  <editor:ProgressBar class="efi" low-value="0" high-value="100" title="ProgressBar"/>
</UXML>
 结果  ?
 文本输入1.TextInputBaseField< TValueType > (X) 所有文本字段的抽象基类 继承自 BaseFieldTraits<string, UxmlStringAttributeDescription>text:字段的文本值max-length:字段可包含的最大字符数。默认值-1设置文本长度没有限制。password:一个布尔值,指示是否应显示字段内容(false,默认值)或使用maskCharacter字符显示。mask-character:字符使用时显示的字段内容password是true。默认是角色*。readonly:boolean指示该字段是只读的(默认值:false)
 2.TextField(X) 可编辑的文本-继承自TextInputBaseField< string >
 multiline:一个布尔值,指示文本字段是在多行(true)还是在一行上显示其文本,忽略文本中的任何换行符(false默认值)
 3.IntegerField(X) 整数(32位)值的文本 在UnityEditor.UIElements命名空间下继承自BaseFieldTraits<int, UxmlIntAttributeDescription>
 4.LongField (X) 长整数(64位)值的文本 在UnityEditor.UIElements命名空间下继承自BaseFieldTraits<long, UxmlLongAttributeDescription>
 5.FloatField(X) 单精度浮点值的文本 在UnityEditor.UIElements命名空间下继承自BaseFieldTraits<float, UxmlFloatAttributeDescription>
 6.DoubleField(X) 双精度浮点值的文本 在UnityEditor.UIElements命名空间下继承自BaseFieldTraits<double, UxmlDoubleAttributeDescription>
 7.Vector2Field(X) 两个文本框,接受按?float?进行编辑的Vector2类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Vector2 >x:X坐标的值y:Y坐标的值
 8.Vector2IntField(X) 两个文本框,接受按?int?进行编辑的Vector2类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Vector2Int >x:X坐标的值y:Y坐标的值
 9.Vector3Field(X) 三个文本框,接受按?float?进行编辑的Vector3类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Vector3 >x:X坐标的值y:Y坐标的值z:Z坐标的值
 10.Vector3IntField(X) 三个文本框,接受按?Int?进行编辑的Vector3类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Vector3Int >x:X坐标的值y:Y坐标的值z:Z坐标的值
 11.Vector4Field(X) 四个文本框,接受按?float?进行编辑的Vector4类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Vector4 >x:X坐标的值y:Y坐标的值z:Z坐标的值w:W坐标的值
 12.RectField(X) 四个文本框,接受按?float?进行编辑的Rect类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Rect >x:左上角X坐标的值y:左上角Y坐标的值w:矩形的宽度h:矩形的高度
 13.RectIIntField(X) 四个文本框,接受按?Int?进行编辑的Rect类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< RectInt >x:左上角X坐标的值y:左上角Y坐标的值w:矩形的宽度h:矩形的高度
 14.BoundsField(X) 六个文本框,接受按?float?进行编辑的Bounds类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< Bounds >cx:中心X坐标的值cy:中心Y坐标的值cz:中心Z坐标的值ex:X的长度ey:Y的长度ez:Z的长度
 15.BoundsIntField(X) 六个文本框,接受按?Int?进行编辑的Bounds类型文本 在UnityEditor.UIElements命名空间下继承自 BaseField< BoundsInt >cx:中心X坐标的值cy:中心Y坐标的值cz:中心Z坐标的值ex:X的长度ey:Y的长度ez:Z的长度
 简单案例4 
 .fraSmall
{
	width:150px;
	height:20px;
}
.fraBig
{
	width:300px;
	height:50px;
}
<?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
    <TextField class="fraSmall" text="TextField"/>
    <editor:IntegerField class="fraSmall"/>
    <editor:LongField class="fraSmall"/>
    <editor:FloatField class="fraSmall"/>
    <editor:DoubleField class="fraSmall"/>
    <editor:Vector2Field class="fraSmall"/>
    <editor:Vector2IntField class="fraSmall"/>
    <editor:Vector3Field class="fraSmall"/>
    <editor:Vector3IntField class="fraSmall"/>
    <editor:Vector4Field class="fraSmall"/>
    <editor:RectField class="fraBig"/>
    <editor:RectIntField class="fraBig"/>
    <editor:BoundsField class="fraBig"/>
    <editor:BoundsIntField class="fraBig"/>
</UXML>
  ?
 PropertyField(X)用于编辑值的标签和字段 在UnityEditor.UIElements命名空间下binding-path:此元素绑定的属性的路径label:该字段的标签
 PropertyControl< int/long/float/double/string > (X)用于编辑字符串类型值的标签和字段 在UnityEditor.UIElements命名空间下继承自BaseField< int/long/float/double/string >value-type:表示值类型的字符串value:该字段的值
 简单案例5 
 .container {
   background-color: rgb(80, 80, 80);
   flex-direction: column;
}
Label {
   background-color: rgb(80, 80, 80);
}
TextField:hover {
   background-color: rgb(255, 255, 0);
}
FloatField {
   background-color: rgb(0, 0, 255);
}
<?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
      <VisualElement name="row" class="container">
        <Label text="Tank Script - Custom Inspector" />
        <editor:PropertyField binding-path="tankName" name="tank-name-field" />
        <editor:PropertyField binding-path="tankSize" name="tank-size-field" />
      </VisualElement>
</UXML>
 C#及对应Editor下的脚本:  
 [ExecuteInEditMode]
public class TankScript : MonoBehaviour
{
    public string tankName = "Tank";
    public float tankSize = 1;
    private void Update()
    {
        gameObject.name = tankName;
        gameObject.transform.localScale = new Vector3(tankSize, tankSize, tankSize);
    }
}
[CustomEditor(typeof(TankScript))]
public class TankEditor : Editor
{
    public override VisualElement CreateInspectorGUI()
    {
        var visualTree = Resources.Load("tank_inspector_uxml") as VisualTreeAsset;
        var uxmlVE = visualTree.CloneTree();
        uxmlVE.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Resources/tank_inspector_styles.uss"));
        return uxmlVE;
    }
}
  ?
 ColorField(X)颜色选择器 在UnityEditor.UIElements命名空间下继承自BaseFieldTraits<Color, UxmlColorAttributeDescription>show-eye-dropper:一个布尔值,指示是否显示(true默认值)滴管器(false)。show-alpha:一个布尔值,指示是否显示alpha控件(true,默认值)或不显示(false)hdr:一个布尔值,指示是使用高动态范围颜色选择器(true)还是正常颜色选择器(false默认值)
 CurveField (X)曲线编辑器 在UnityEditor.UIElements命名空间下继承自BaseField< AnimationCurve >
 GradientField(X)渐变编辑器 在UnityEditor.UIElements命名空间下继承自BaseField< Gradient >
 ObjectField(X)对象选择器 在UnityEditor.UIElements命名空间下继承自BaseField< Object >allow-scene-objects:一个布尔值,指示场景对象是否可以选择(true,默认)或不选择(false)
 InspectorElement在Inspector中显示属性的元素 在UnityEditor.UIElements命名空间下继承自 BindableElement
 简单案例6 
 <?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
     <editor:ColorField />
     <editor:CurveField />
     <editor:GradientField />
     <editor:ObjectField />
</UXML>
  ?
 工具栏相关Toolbar 用于保存工具栏的容器 在UnityEditor.UIElements命名空间下
 ToolbarButton(X) 工具栏按钮 在UnityEditor.UIElements命名空间下继承自 Button
 ToolbarToggle(X) 工具栏开关 在UnityEditor.UIElements命名空间下继承自 Toggle
 ToolbarMenu(X) 工具栏的下拉菜单 在UnityEditor.UIElements命名空间下继承自 TextElement
 ToolbarSearchField(X) 工具栏的搜索字段 在UnityEditor.UIElements命名空间下
 ToolbarPopupSearchField(X) 带有搜索选项弹出菜单的搜索字段 在UnityEditor.UIElements命名空间下继承自 ToolbarSearchField
 ToolbarSpacer(X) 在工具栏按钮之间插入固定数量的空白的元素 在UnityEditor.UIElements命名空间下
 简单案例7 
 <?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
       <editor:Toolbar>
         <editor:ToolbarButton text="Button"/>
         <editor:ToolbarToggle text="Toggle"/>
         <editor:ToolbarMenu text="Menu"/>
         <editor:ToolbarSearchField text="SearchField"/>
         <editor:ToolbarPopupSearchField text="popupSearchField"/>
       </editor:Toolbar>
</UXML>
 ? ? ListView(X)显示元素列表 item-height:列表中每个Item的高度值
 ScrollView可滚动视图,带有水平和垂直滚动条 mode:滚动视图的模式,默认为 ScrollViewMode.Verticalshow-horizontal-scroller:一个布尔值,指示是否显示水平滚动条; 默认falseshow-vertical-scroller:一个布尔值,指示是否显示垂直滚动条; 默认falsehorizontal-page-size:水平滚动条的大小vertical-page-size:垂直滚动条的大小
 TreeView(X)用于在树层次结构中显示元素的视图 item-height:列表中每个Item的高度值
 PopupWindowUIElements窗口,显示在其他内容之上  
 .fra
{
	width:200px;
	height:100px;
}
.fras
{
	width:160px;
	height:80px;
}
<?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xmlns:editor="UnityEditor.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">
         <PopupWindow class="fra" text="wowowo">
           <ScrollView class="fras">
             <Label text="啊"/>
             <Label text="啊"/>
             <Label text="啊"/>
             <Label text="啊"/>
             <Label text="啊"/>
             <Label text="啊"/>
           </ScrollView>
         </PopupWindow>
</UXML>
  ?
 官方案例大家可以通过Unity Hub下载最新Unity2019.2.0b版本,然后通过Windows > UI > UIElements Samples打开。  ?
 在这里可以看到常用组件用法的Sample。 |