|
一.简介
1、两个文件
.UXML :界面信息文件,保存了用户界面的逻辑结构
<ui:UXML
xmlns:ui=&#34;UnityEngine.UIElements&#34;
xmlns:uie=&#34;UnityEditor.UIElements&#34;
xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
engine=&#34;UnityEngine.UIElements&#34;
editor=&#34;UnityEditor.UIElements&#34;
noNamespaceSchemaLocation=&#34;../../UIElementsSchema/UIElements.xsd&#34;
editor-extension-mode=&#34;False&#34;>
<!--USS文件,保存资源路径+GUID,编辑器模式下均通过路径进行加载-->
<Style src=&#34;project://database/Assets/CustomUss1.uss?fileID=7433441132597879392&amp;guid=14c2bcd9a5eefc24889c0596e1209921&amp;type=3#CustomUss1&#34; />
<!--ui:VisualElement(标签:类型为VisualElement), style(属性,此处为背景图片) = “xxx”(属性值)-->
<ui:VisualElement style=&#34;background-image: url(&apos;project://database/Assets/numthreads%E7%A4%BA%E4%BE%8B.jpg?fileID=2800000&amp;guid=af712550a72825747b7d66b740e7d1a0&amp;type=3#numthreads示例&apos;);&#34;>
<ui:Label text=&#34;Label&#34; display-tooltip-when-elided=&#34;true&#34; />
</ui:VisualElement>
<ui:Label text=&#34;Label&#34; display-tooltip-when-elided=&#34;true&#34; />
</ui:UXML>
.USS: 样式选择器
2、一个类型
VisualElement:所有UI元素的基类,元素采用相对坐标和绝对坐标的机制在布局中排开。在UI Toolkit中,每个VisualElement都可以进行嵌套,子对象将按照父对象的设置进行布局。
如何获取一个控件对象:
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
UIDocument document = GetComponent<UIDocument>();
var root = document.rootVisualElement;
Button button = root.Q<Button>(&#34;MyBtn&#34;);
button.clicked += () =>
{
Debug.Log(&#34;我被点了&#34;);
};
button.RegisterCallback<PointerOutEvent>((evt) =>
{
Debug.Log(&#34;鼠标挪走了&#34;);
});
}
}
如何自定义一个VisualElement:
public class StatusBar : VisualElement
{
//UI资源路径
private const string UXML_PATH = &#34;Assets/status.uxml&#34;;
//工厂:使UI工具包在读取UXML文件时能够实例化对应类型
public new class UxmlFactory : UxmlFactory<StatusBar, UxmlTraits> { }
//特征类:UXML文件中的定义
public new class UxmlTraits : VisualElement.UxmlTraits
{
//创建xml文件中属性类实例
UxmlStringAttributeDescription _status = new UxmlStringAttributeDescription { name = &#34;statusww&#34; };
UxmlStringAttributeDescription _testStr = new UxmlStringAttributeDescription { name = &#34;TestStr&#34; };
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
StatusBar statusBar = ve as StatusBar;
//属性赋值
statusBar.status = _status.GetValueFromBag(bag, cc);
statusBar.TestStr = _testStr.GetValueFromBag(bag, cc);
}
}
public string status { get; set; }
private Label _testStr;
private UnityEngine.UIElements.Button _button;
private int _num = 0;
private string _status;
public string TestStr
{
get { return _testStr.text; }
set { _testStr.text = value; }
}
//必须提供一个默认构造函数
public StatusBar()
{
_status = String.Empty;
//加载该类型对应的VisualTree
VisualTreeAsset template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UXML_PATH);
template.CloneTree(this);
Init();
}
public void Init()
{
//绑定组件
_testStr = this.Q<Label>(&#34;testStr&#34;);
_button = this.Q<UnityEngine.UIElements.Button>(&#34;testBtn&#34;);
TestStr = _num.ToString();
_button.clicked += _BtnOnClick;
}
public void UnInit()
{
}
private void _BtnOnClick()
{
TestStr = Random.Range(0, 100).ToString();
}
}
二.原理
前置:
IMGUI:
每帧遍历布局树,对每个UI元素设置渲染状态、生成网格顶点、执行DrawCall。
UGUI:
在界面改变时生成网格顶点,并基于Canvas进行合批,将材质相同可以合批的网格进行合批
1、UI Toolkit DrawCall合并策略:
策略:将每个参与渲染的VisualElement放在队列中,直到队列中出现第九个与之前元素使用的不同的Texture或Atlas,之前的元素被合并为一个DrawCall
UI Toolkit并不关心图集完全依据界面布局进行DrawCall合并,UI Toolkit 将所有几何数据保存在一个Vb/IB(顶点缓冲区/顶点索引缓冲区)中 , 底层使用UberShader(全能着色器:在Shader中使用宏定义来提高着色器的复用率,执行分支),这样可以将原先在CPU的计算损耗转移到GPU中。对于在界面中运行时可能会发生变化的元素,UIR引入GPU分配器来管理 来自VB/IB的顶点/索引分配,如果元素变化就在同一个VB/IB中分配一个新的控件来填充他的新顶点/索引,其元素不变,并且保证渲染顺序。
2、对比测试
IMGUI与UI Toolkit
IMGUI
UI Toolkit
UGUI 与 UI Toolkit
UGUI Profiler
UGUI FrameDebugger
UI Toolkit Profiler
UI Toolkit
3、结论:
新一代UI Toolkit在性能方面有很大的提升,具体表现在以下几个方面
(1)使用UXML文件 来保存界面布局信息
在UGUI中以GameObject -> Prefab的形式来保存一份UI界面数据,通常一个控件对应的Prefab将会保存:GameObject 、 RectTransfrom、 CanvasRendered、 MonoBehaviour 这些数据,这其中大部分数据都并不需要并且就算不改变颜色、位置等信息,这部分数据也需要保存。而在UXML中精简了这部分数据结构,只保存最精简的描述信息.同时这种方式存储界面信息也更容易进行UI界面的迁移。
<!--XML声明,可选,如果使用声明则必须在第第一行,且前面不能出现其他任何内容包括空格-->
<?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?>
<ui:UXML
xmlns:ui=&#34;UnityEngine.UIElements&#34;
xmlns:uie=&#34;UnityEditor.UIElements&#34;
xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
engine=&#34;UnityEngine.UIElements&#34;
editor=&#34;UnityEditor.UIElements&#34;
noNamespaceSchemaLocation=&#34;../../UIElementsSchema/UIElements.xsd&#34;
editor-extension-mode=&#34;False&#34;>
<!--当前界面所包含的元素 及对应属性-->
<ui:Label text=&#34;Label&#34; display-tooltip-when-elided=&#34;true&#34; class=&#34;test2&#34; />
<ui:Button text=&#34;Button&#34; display-tooltip-when-elided=&#34;true&#34; />
</ui:UXML>(2)结合UGUI和SpriteRenderer 的DrawCall合批
使用者可以不再关心图集,UI Toolkit中完全按照界面布局的方式进行合批,能容纳8张Texture和一个 Font Texture。平衡了CPU和GPU的开销能够大量减少DC。这都得益于UberShader 对渲染状态切换的支持。
三.适用方向
1.编辑器页面
通过UIBuilder可以简洁直观的绘制出应用UI界面,无需代码策划也可以参与到UI的设计与绘制。并且由于DrawCall的优化使用UI Toolkit代替 IMGUI可以大大提高编辑时性能
2.简单的Runtime UI界面
由于目前UI Toolkit 还有很多未解决的问题:UI和粒子特效叠层, UI和3D模型叠层,3D界面、K帧动画等所以 UI Toolkit只能用来做一些简单无特效的UI应用界面。同时UI Toolkit支持与UGUI的混用,可以在一些纯粹的UI界面使用这种技术。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|