第七课 Unity编辑器创建的资源优化_UI篇(UGUI)

上期我们学习了简单的Scene优化,接下来我们继续编辑器创建资源的UGUI优化

UI篇(UGUI)

优化UGUI应从哪些方面入手?

可以从CPU和GPU两方面考虑,CPU方面,避免触发或减少Canvas的Rebuild和Rebatch,减少Drawcall,减少CPU处理顶点的时间;GPU方面,降低Overdraw,缩小纹理大小。

Canvas的Batch构建过程(The Batch building process),简称Rebatch


Batch 构建过程是指Canvas通过结合网格绘制它所承载的UI元素,生成适当的渲染命令发送给Unity图形流水线。Batch的结果被缓存复用,直到这个Canvas被标为dirty,当Canvas中某一个构成的网格改变的时候就会标记为dirty,这个Dirty就会触发Rebatch。

Rebatch不仅有批处理排序,还有网格合并之类的。Canvas的网格从那些Canvas下的CnavasRenderer组件中获取,但不包含任何子Canvas。

所以对于UGUI的性能分析,要分开两点

Canvas的批处理过程 Rebatch
Graphic 和Layout的 Rebuild
这两点,都会影响性能。但是Rebatch是有多线程的加持的,而Rebuild是在主线程的。

Rebuild自身会有性能消耗,同时Rebuild会触发Rebatch。
Rebatch除了被Rebuild触发,还会被其他情况触发。
Rebatch的性能上的问题,在电脑上比较难看的出来,因为有多线程加持。


Rebuild过程

Rebuild 过程是指Layout和Graphic组件的网格被重新计算,这是在CanvasUpdateRegistry类中执行的。这是一个C#类,打开UI的源码,它里面的一个函数,叫做PerformUpdate,当一个Canvas组件触发它的WillRenderCanvases事件时,这个方法就会被执行。这个事件每帧调用一次,这也是为什么我们看Profile的时候,出现性能高峰的总是会看到WillRenderCanvases的原因了。

PerformUpdate的运行过程分3步:

按顺序遍历调用Dirty的Layout组件的Rebuild函数
要求任何已注册的裁剪组件(例如Mask),剔除所有裁剪的组件。这是通过ClippingRegistry.Cull完成的。
按顺序遍历调用Dirty的Graphic组件的Rebuild函数


Rebuild分为 Layout Rebuild 和 Graphic Rebuild

Layout Rebuild
要重新计算一个或多个Layout组件中包含的组件的适当位置(和可能的大小),必须按其适当的层次结构顺序应用Layouts。在GameObject层次结构中靠近根部的布局可能会更改嵌套在其中的任何布局的位置和大小,因此必须首先进行计算。
为此,UGUI根据层次结构中的深度对dirty的Layout组件列表进行排序。层次结构中较高的Layout(即,父节点较少)将被移到列表的前面。
然后,排序好的Layout组件的列表将被rebuild,在这个步骤Layout组件控制的UI元素的位置和大小将被实际改变。

Graphic Rebuild
当Graphic组件被rebuild的时候,UGUI会将控制权传递给ICanvasElement接口的Rebuild方法。Graphic执行了这一步,并在rebuild过程中的PreRender阶段运行了两个不同的rebuild步骤:

如果顶点数据已标记为Dirty(例如,当组件的RectTransform的大小更改时),则将重新构建网格。
如果将材质数据标记为Dirty(例如,当更改组件的材质或纹理时),则将更新附加的Canvas Renderer的材质。
Graphic的Rebuild不会按照Graphic组件的特殊顺序进行,并且不需要任何排序操作。

Rebatch和Rebuild的触发条件总结
 

触发Rebatch的条件:

当Canvas下有Mesh发生改变时,如:
SetActive
Transform属性变化
Graphic的Color属性变化(改Mesh顶点色)
Text文本内容变化
Depth发生变化
触发Rebuild的条件:

Layout修改RectTransform部分影响布局的属性
Graphic的Mesh或Material发生变化
Mask裁剪内容变化

Unity UI性能的四类问题

1. Canvas Re-batch 时间过长
2. Canvas Over-dirty, Re-batch次数过多
3. 生成网格顶点时间过长
4. Fill-rate overutilization

Canvas画布

Canvas负责管理UGUI元素,负责UI渲染网格的生成与更新,并向GPU发送DrawCall指令。

Canvas Re-batch过程(合批)

1. 根据UI元素深度关系进行排序
2. 检查UI元素的覆盖关系
3. 检查UI元素材质并进行合批

合批对比

UGUI渲染细节

  • UGUI中渲染是在Transparent半透明渲染队列中完成的,半透明队列的绘制顺序是从后往前画,由于UI元素做Alpha Blend,我们在做UI时很难保障每一个像素不被重画,UI的Overdraw太高,这会造成片元着色器利用率过高,造成GPU负担。
  • UI SpriteAtlas图集利用率不高的情况下,大量完全透明的像素被采样也会导致像素被重绘,造成片元着色器利用率过高;同时纹理采样器浪费了大量采样在无效的像素上,导致需要采样的图集像素不能尽快的被采样,造成纹理采样器的填充率过低,同样也会带来性能问题。如下图

Re-Build过程(重构)

1.在WillRenderCanvases事件调用PerformUpdate::CanvasUpdateRegistry接口

通过ICanvasElement.Rebuild方法重新构建Dirty的Layout组件

通过ClippingRegistry.Cullf方法,任何已注册的裁剪组件Clipping Compnents(Such as Masks)的对象进行裁剪剔除操作

任何Dirty的 Graphics Compnents都会被要求重新生成图形元素

2.Layout Rebuild

UI元素位置、大小、颜色发生变化

优先计算靠近Root节点,并根据层级深度排序

3.Graphic Rebuild

顶点数据被标记成Dirty

材质或贴图数据被标记成Dirty

使用Canvas的基本准则

  1. 将所有可能打断合批的层移到最下边的图层,尽量避免UI元素出现重叠区域,尤其是一些很小的ui元素,比如字体,是一个很小的矩形,容易被忽略,但是每一帧都会导致重新合批
  2. 可以拆分使用多个同级或嵌套的Canvas来减少Canvas的Rebatch复杂度
  3. 拆分动态和静态对象放到不同Canvas下,来避免动态UI元素导致每帧都要做太复杂的canvas Rebatch操作
  4. 不使用Layout组件,这样就不会有太多的rebuild 的过程了,同样可以减少Rebatch的时间消耗
  5. Canvas的RenderMode尽量Overlay模式,减少Camera调用的开销

 UGUI射线(Raycaster)优化

  1. 必要的需要交互UI组件才开启“Raycast Target”
  2. 开启“Raycast Targets”的UI组件越少,层级越浅,性能越好
  3. 对于复杂的控件,尽量在根节点开启“Raycast Target”
  4. 对于嵌套的Canvas,OverrideSorting属性会打断射线,可以降低层级遍历的成本 

UGUI优化思路 

1.Canvas 子节点动静分离

在UI Canvas 中进行子节点动静分离,主要是将频繁变动的UI元素,如动态文本动画图标与相对静态的元素,如背景图,固定按钮分开管理。这样可以减少不必要的重绘,提高性能。通常将动态节点放在一个单独的Canvas或者层级下。在需要更新时只重绘该部分,避免影响影响静态元素。

2.Sprite Packer

是将多个小的UI精灵纹理合并成一个大纹理图集的工具,这有助于减少纹理加载次数和内存占用,提高渲染性能

3.运行时动态合并图集

当然UI运行时动态合并图集性能,

1.减少合并频率

2.合并前筛选出真正需要合并的元素,避免不必要的操作

3.尽量采用多线程技术来处理合并任务,防止阻塞主线程

4.对图集大小合理限制,防止内存占用过大

4.自动布局组件 

不要使用Layout组件,Layout组件性能消耗相对昂贵,会大大地增加Canvas.SendWillRenderCanvases函数耗时,利用好RectTransform同样可实现简单布局。

5.动态加载和裁剪

对于UI动态加载,可以采用对象池来管理UI元素,避免频繁的实例化和销毁,在裁剪方面,设置合理的裁剪区域,减少不必要的计算,同时利用层级结构和遮挡关系,减少渲染压力。

6.组件中自定义材质球打断合批

在UI组件中,自定义的材质球打断合批主要是因为其改变了渲染状态,当材质球的shader,纹理等属性与其他UI组件不同时,就无法合批渲染,可以通过统一材质属性或者使用相同的材质模板来减少这种打断,提高渲染效率

7. Raycat Target

1.只需要在交互的UI元素上勾选,如按钮等。

2.使用射线检测范围更小的组件替换

3.将不需要检测的UI元素放在不勾选Raycat Target的父物体下,利用层级关系减少不必要的检测

8.不可见元素 Cull Transparent Mesh

对于UI中不可见元素,使用Cull Transparent Mesh(剔除透明网格)可以提高性能,它通过不渲染这些不可见的透明元素,减少了渲染计算量和内存占用,一般在合适的渲染管线设置中开启此功能即可

9.UI 字体(TTF和OTF)

1.选择简洁的字体,减少复杂笔画

2.使用字体图集,合并常用字符纹理

3.根据需要动态加载字体资源

4.避免字体框重叠,造成合批打断

5.字体网格重建,UIText组件发生变化时,父级对象发生变化时,UI组件或其父对象enable和disable时

谨慎使用Text的Best Fit选项,虽然这个选项可以动态的调整字体大小以适应UI布局而不会超框,但其代价是很高的,一方面是适配本身在调整文本框大小时有CPU耗时开销,另一方面每个字号下新生成的字都会在Font Texture上占用一个字的大小,容易导致Font Texture过大(这个类似图集,当Font Texture当前大小放不下时才会占用更多内存)。这个特定问题已在 Unity 5.4 中得到纠正,Best Fit 不会不必要地扩展字体的纹理图集,但仍然比静态大小的文本慢得多。

10.计时器和倒计时,触发UI重绘

11.Sprite 九宫格设置

如果是较大的背景图的UI元素建议也要使用Sprite的九宫格拉伸处理,充分减小UI Sprite大小,提高UI Atlas图集利用率

12.GameObject Active/Deactive -> UI CanvasGroup Alpha

13.Canvas Pixel Perfect

谨慎使用Canvas的Pixel Perfect选项,该选项会使得ui元素在发生位置变化时,造成layout Rebuild。(比如ScrollRect滚动时,如果开启了Canvas的pixel Perfect,会使得Canvas.SendWillRenderCanvas消耗较高)

14.shadow 顶点和面数翻倍

15.outline 顶点和面数翻倍

慎用自带组件Outline和Shadow,都是通过重复绘制多个Mesh实现的,其中Shadow绘制为原文本Mesh的2倍,而Outline为5倍,对渲染面数、顶点数,BuildBatch和SendWillRenderCanvases的耗时,Overdraw都有影响。如经常用,可考虑其它方式,如TextMeshPro,或把阴影和描边做到字体里。

16.元素 position Z值不为 0 打断合批

17.Mask vs RectMask2D

Mask依赖Image组件,占用两个Batch,多一倍Overdraw,可以裁剪任意形状。
RectMask2D不依赖Image组件,不占用Batch,没有Overdraw,只能裁剪规则形状。
因此,一般情况下,规则的裁剪尽量用RectMask2D代替Mask,特别是在使用ScrollRect时。
RectMask2D一定比Mask好吗?并不是,Mask间是可以合批的,而RectMask2D间不行,因此当要使用多Mask时,如背包界面中的道具格子,每个格子有裁剪需求时,尽量用Mask,Mask可合批,而RectMask2D会导致合批被打断。

因此:

  • 当一个界面只有一个Mask,那么RectMask2D优于Mask;
  • 当有两个Mask,那么两者差不多;
  • 当大于两个Mask,那么Mask优于RectMask2D。

18.避免多层 激活UI元素堆叠

19.加载页/活动图等几乎充满屏幕的UI,关闭场景相机渲染,或渲染一张RT模糊后作背景

20.文本组件建议使用Text Mesh Pro 

21.界面操作一般会触发UI的开关或者隐藏显示,Active 和DeActive,必然会造成UI重建。而采用控制Canvas组件的激活与关闭。

22.不需要参与点击事件的Canvas取消激活Graphic Raycaster 脚本。

射线检测遍历所有将'Raycast Target'设置为true的Graphic组件。每一个Raycast Target都会被进行测试。如果一个Raycast Target通过了所有的测试,那么它就会被添加到“被命中”列表中。
每个Graphic Raycaster都将遍历 Transform层次结构一直到根,此操作的成本与层次结构的深度成比例线性增长。因此进行射线检测的元素越多,层级越深,消耗越高。
鉴于所有射线检测目标都必须由Graphic Raycaster进行测试,因此最好的做法是仅在必须接收点击事件的UI组件上启用'Raycast Target'设置。检测目标列表越少,遍历的层级越浅,每次射线检测的速度越快。

23.持续性的UI动态效果特效,最好采用特效的方式制作,脱离UI系统。

24.动态合静态的UI 要分开,分别挂上canvas。

25. 在使用非全屏但模态对话框时,建议使用**OnDemandRendering**接口,对渲染进行降频。

26.优化裁剪UI Shader,根据实际使用需求移除多余特性关键字。

27.滚动视图Scroll View优化

  •     使用RectMask2d组件裁剪
  •     使用基于位置的对象池作为实例化缓存

这篇文章是摘取自多个大神的文章,所以会有知识点重复的情况,但是我主张的是可以重复,但是知识点一定要全!!!

今天是2024年11月30日

重复一段毒鸡汤来勉励我和你

你的对手在看书

你的仇人在磨刀

你的闺蜜在减肥

隔壁的老王在练腰

而你在干嘛?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/928304.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW MathScript工具包对运行速度的影响及优化方法

LabVIEW 的 MathScript 工具包 在运行时可能会影响程序的运行速度,主要是由于以下几个原因: 1. 解释型语言执行方式 MathScript 使用的是类似于 MATLAB 的解释型语言,这意味着它不像编译型语言(如 C、C 或 LabVIEW 本身的 VI&…

中国移动量子云平台:算力并网590量子比特!

在技术革新的浪潮中,量子计算以其独特的并行处理能力和指数级增长的计算潜力,有望成为未来技术范式变革和颠覆式创新应用的新源泉。中国移动作为通信行业的领军企业,致力于量子计算技术研究,推动量子计算产业的跨越式发展。 量子云…

pytest(二)excel数据驱动

一、excel数据驱动 excel文件内容 excel数据驱动使用方法 import openpyxl import pytestdef get_excel():excel_obj openpyxl.load_workbook("../pytest结合数据驱动-excel/data.xlsx")sheet_obj excel_obj["Sheet1"]values sheet_obj.valuescase_li…

文库 | 从嬴图的技术文档聊起

在技术的浩瀚海洋中,一份优秀的技术文档宛如精准的航海图。它是知识传承的载体,是团队协作的桥梁,更是产品成功的幕后英雄。然而,打造这样一份出色的技术文档并非易事。你是否在为如何清晰阐释复杂技术而苦恼?是否纠结…

flask的第一个应用

本文编写一个简单的实例来记录下flask的使用 文章目录 简单实例flask中的路由无参形式有参形式 参数类型本文小结 简单实例 flask的依赖包都安装好之后,我们就可以写一个最简单的web应用程序了,我们把这个应用程序命名为first.py: from flask import Fla…

【UE5 C++】判断两点连线是否穿过球体

目录 前言 方法一 原理 代码 测试 结果 方法二 原理 一、检查连线与球体的相交情况 二、检查距离与球体半径的关系 三、检查连线与球体的相交 代码 前言 通过数学原理判断空间中任意两点的连线是否穿过球体,再通过射线检测检验算法的正确性。 方法一 …

Python办公——openpyxl处理Excel每个sheet每行 修改为软雅黑9号剧中+边框线

目录 专栏导读背景1、库的介绍①:openpyxl 2、库的安装3、核心代码4、完整代码5、最快的方法(50万行44秒)——表头其余单元格都修改样式总结 专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍…

Figma入门-约束与对齐

Figma入门-约束与对齐 前言 在之前的工作中,大家的原型图都是使用 Axure 制作的,印象中 Figma 一直是个专业设计软件。 最近,很多产品朋友告诉我,很多原型图都开始用Figma制作了,并且很多组件都是内置的&#xff0c…

8. Debian系统中显示屏免密码自动登录

本文介绍如何在Debian系统上,启动后,自动免密登录,不卡在登录界面。 1. 修改lightDM配置文件 嵌入式Debian系统采用lightDM显示管理器,所以,一般需要修改它的配置文件/etc/lightdm/lightdm.conf,找到[Seat…

Unity类银河战士恶魔城学习总结(P156 Audio Settings音频设置)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了音频的大小设置与保存加载 音频管理器 UI_VolumeSlider.cs 定义了 UI_VolumeSlider 类,用于处理与音频设置相关的…

控制访问权限

Swift中的控制访问权限有5种,分别是private,fileprivate,public,open,intelnal。 如果我们没有写访问权限关键字时,默认的访问权限是intelnal 访问控制权限从高到低的顺序是:open > public…

单例模式的析构学习

1、例子 如果单例对象是类的static成员&#xff0c;那么在程序结束时不会调用类的析构函数&#xff0c;如下&#xff1a; #include <iostream> using namespace std;class A{ private:static A* m_ins;//声明&#xff0c;静态指针成员A(){} public:static A* getIns(){…

Function Arguments and Function Parameters (函数的实参和函数的形参)

Function Arguments and Function Parameters {函数的实参和函数的形参} 1. Object-Oriented Programming Using C2. Function Arguments and Function ParametersReferences 1. Object-Oriented Programming Using C https://icarus.cs.weber.edu/~dab/cs1410/textbook/index…

[SWPUCTF 2021 新生赛]gif好像有点大

[SWPUCTF 2021 新生赛]gif好像有点大 帧解一下 找到这个二维码用软件CQR解开一下 得到flag NSSCTF{The_G1F_ls_T00_b1g} [BJDCTF 2020]base?? 给了我们base64加密的密文 用python直接解密 import base64 dict{0: J, 1: K, 2: L, 3: M, 4: N, 5: O, 6: x, 7: y, 8: U, 9: …

嵌入式蓝桥杯学习1 点亮LED

cubemx配置 1.新建一个STM32G431RBT6文件 2.在System-Core中点击SYS&#xff0c;找到Debug&#xff08;设置为Serial Wire&#xff09; 3.在System-Core中点击RCC&#xff0c;找到High Speed Clock(设置为Crystal/Ceramic Resonator) 4.打开Clock Configuration &#xff0…

机器学习周志华学习笔记-第13章<半监督学习>

机器学习周志华学习笔记-第13章&#xff1c;半监督学习&#xff1e; 卷王&#xff0c;请看目录 13半监督学习13.1 生成式方法13.2 半监督SVM13.3 基于分歧的方法13.4 半监督聚类 13半监督学习 前面我们一直围绕的都是监督学习与无监督学习&#xff0c;监督学习指的是训练样本包…

安装MySQL 5.7 亲测有效

前言&#xff1a;本文是笔者在安装MySQL5.7时根据另一位博主大大的安装教程基础上做了一些修改而成 首先在这里表示对博主大大的感谢 下面附博主大大地址 下面的步骤言简意赅 跟着做就不会出错 希望各位读者耐下心来 慢慢解决安装中出现的问题~MySQL 5.7 安装教程&#xff08;全…

Navicat连接SQL Server及SpringBoot连接SQL Server(jtds)

Navicat连接SQL Server 安装自带的SQL Server客户端 去到Navicat安装目录&#xff0c;找到安装程序&#xff0c;安装即可。 安装对应版本的Microsoft ODBC Driver for SQL Server 打开Navicat输入对应的SQL Server相关信息 然后点测试连接&#xff0c;提示连接成功。 Spr…

vue+uniapp+echarts的使用(H5环境下echarts)

1.安装 npm install echarts4.9.0 --save // 带版本号 2.main.js中全局引用 // import echarts from echarts // 如果是5.0以上版本用这个 import * as echarts from echarts Vue.prototype.$echartsecharts 3.使用 <template><view id"box" style"w…

单片机的中断系统

作者简介 彭煜轩&#xff0c;男&#xff0c;银川科技学院计算机与人工智能学院&#xff0c;2022级计算机与科学技术8班本科生&#xff0c;单片机原理及应用课程第3组。 指导老师&#xff1a;王兴泽 电子邮件&#xff1a;1696409709qq.com 前言 本篇文章是参考《单片机原理…