首页 > 其他分享 >第七课 Unity编辑器创建的资源优化_UI篇(UGUI)

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

时间:2024-11-30 20:59:05浏览次数:8  
标签:Canvas Graphic Layout 第七课 Rebuild Unity UI 组件

上期我们学习了简单的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接口
  2. 通过ICanvasElement.Rebuild方法重新构建Dirty的Layout组件
  3. 通过ClippingRegistry.Cullf方法,任何已注册的裁剪组件Clipping Compnents(Such as Masks)的对象进行裁剪剔除操作
  4. 任何Dirty的 Graphics Compnents都会被要求重新生成图形元素
  5. Layout Rebuild
  6. UI元素位置、大小、颜色发生变化
  7. 优先计算靠近Root节点,并根据层级深度排序
  8. Graphic Rebuild
  9. 顶点数据被标记成Dirty
  10. 材质或贴图数据被标记成Dirty

使用Canvas的基本准则

  1. 将所有可能打断合批的层移到最下边的图层,尽量避免UI元素出现重叠区域
  2. 可以拆分使用多个同级或嵌套的Canvas来减少Canvas的Rebatch复杂度
  3. 拆分动态和静态对象放到不同Canvas下。
  4. 不使用Layout组件
  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 字体

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

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

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

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

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

11.Sprite 九宫格设置

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。

今天是2024年11月30日

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

你的对手在看书

你的仇人在磨刀

你的闺蜜在减肥

隔壁的老王在练腰

而你在干嘛?

标签:Canvas,Graphic,Layout,第七课,Rebuild,Unity,UI,组件
From: https://blog.csdn.net/qq_34800671/article/details/144157882

相关文章

  • 泷羽sec学习--Burp Suite之基本介绍
     学习内容来自B站UP:泷羽sec微信公众号:泷羽sec一、基本介绍BurpSuite是一款用于Web应用程序安全测试的集成平台。它是由PortSwigger公司开发的,是渗透测试人员、安全研究人员和Web开发人员检查和分析Web应用程序安全问题的重要工具。它提供了一个直观的图形化界......
  • 【Unity 水面着色器插件】Stylized Water Toon Shader - Mobile Ready 专为低性能平台
    StylizedWaterToonShader-MobileReady是一款为Unity开发者设计的水面着色器插件,专为低性能平台(如移动设备)优化,提供高质量的卡通风格水面效果。该插件通过简化的渲染方式和丰富的视觉效果,使开发者能够在移动端或其他性能受限的平台上实现流畅的水面表现,适用于多种游戏......
  • 【Unity 特效插件】Trails FX 帮助开发者在游戏中实现物体移动时产生的尾迹效果
    TrailsFX是一款专为Unity开发者设计的特效插件,用于创建动态的尾迹效果(TrailEffects)。这款插件提供了一种快速而高效的方式,帮助开发者在游戏中实现物体移动时产生的尾迹效果,如快速移动的物体、飞行物、粒子效果等。无论是用于角色技能、武器攻击、物体轨迹,还是火焰、光影......
  • 【Unity 任务系统工具】Quests 2 | Game Creator 2 强大的任务系统,用于管理和设计复杂
    Quests2|GameCreator2是由CatsoftWorks开发的Unity插件,是GameCreator2插件套件的一部分。它为开发者提供了一个强大的任务系统,用于管理和设计复杂的游戏任务、支线任务、日常任务等。这个插件能够帮助开发者轻松地创建任务链、条件触发和奖励系统,并与GameCre......
  • 【Unity 战斗插件】ABC Integration: Game Creator 2
    ABCIntegration:GameCreator2是一个为GameCreator2框架开发的插件,旨在将ABC(Action-BasedCombat)系统与GameCreator2集成。ABC是一个专注于动作战斗的系统,它可以轻松地让开发者为自己的游戏添加复杂的战斗机制、攻击动作和技能系统。通过该插件,开发者能够快......
  • 安装BurpSuite
    BurpSuite版本有社区版和专业版,社区版只能实现基本需求:抓包改包,爆破等等。专业版可以实现社区版不能实现的功能,如漏洞扫描等等。kali中是安装了的社区版,免费的,但是想要用专业版需要付费(用点科技可以实现破解)安装BurpSuite我们以Windows为例,安装BurpSuite专业破解版本。首先......
  • BurpSuite使用篇--抓包方法与解码器
    BurpSuite是一个web渗透利器,可以抓包改包也可以扫描漏洞,将漏洞扫描和利用集成化一体,更可以支持外部插件拓展,非常牛的工具。那我们怎么使用呢?使用BurpSuite老版本中BurpSuite需要在浏览器中配置本地代理,还需要导入证书,非常不方便,新版本中BurpSuite自带一个浏览器,不需要经过浏......
  • Unity类银河战士恶魔城学习总结(P153 Audio Manager音频)
    【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/本章节添加了循环播放的BGM,并且给武器攻击加上了音效音频管理器AudioManager.cs1.类的功能核心目标:管理游戏中的音频播放,包括:播放和停止音效......
  • Unity类银河战士恶魔城学习总结(P154 Audio Distance Limite音频距离限制)
    【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/本章节给骷髅战士加上了音频,并且限制了产生音效的范围可爱的骷髅战士AudioManager.cs      关键字段AudioManagerinstance实现单例模式,确......
  • Unity Mask原理及自定义遮罩
    主要内容StencilBuffer是什么?自定义Shader来实现遮罩UnityMask的原理1.什么是StencilBufferGPU在渲染前会为每个像素点分配一个1字节(8位)大小的内存区域,即StencilBuffer。在决定是否要渲染某个像素点之前,会将它当前的StencilBuffer的值与某个参考值(stencilID)进行指定......