Unity - 性能优化实战07 - UGUI优化

一、Canvas Batch

一个Canvas绘制Mesh的过程中,如果每个UI元素都绘制一次(DrawCall),则耗时会很长。因此Canvas会先对其UI元素按照材质和渲染顺序排序,将能够一起绘制的UI元素合并到一个Mesh中,然后绘制。这样可以有效减少DrawCall


二、ReBuild

  • ReBuild是Canvns ReBatch过程中完成的

  • ReBuild是重建UI元素时的操作,它会改变UI的Mesh信息,进而触发ReBatch。当修改了UI元素的缩放,尺寸,材质,旋转等信息时都会触发重建

  • 在WillRenderCanvases事件调用PerformUpdate::CanvasUpdateRegistry接口

    • 通过ICanvasElement.Rebuild方法重新构建Dirty的Layout组件
    • 通过ClippingRegistry.Cullf方法,任何已注册的裁剪组件Clipping Compnents(Such as Masks)的对象进行裁剪剔除操作
    • 任何Dirty的 Graphics Compnents都会被要求重新生成图形元素
  • Layout Rebuild

    • UI元素位置、大小、颜色发生变化
    • 优先计算靠近Root节点,并根据层级深度排序
  • Graphic Rebuild

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

三、Canvas和Graphic

  • Canvas负责管理UGUI元素,负责UI渲染网格的生成与更新,并向GPU发送DrawCall指令
  • UI组件的基类是Graphic,Graphic核心是组织Mesh和Material传到底层(CanvasRenderer)
  • CanvasRenderer将Mesh和Material传递给Canvas,Canvas做合批。CanvasRenderer的两个核心SetMesh和SetMaterial。每个Graphic有一个CanvasRenderer,保存了保存当前元素的Mesh和材质。一个Graphic为dirty,Canvas就要重新合批

四、UGUI渲染细节

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

五、Unity UI性能的四类问题

1.1 Canvas Re-batch 时间过长

  • 指Canvas分析其UI节点信息,生成最优批次的过程

  • 耗时:节点数量,层级深度,元素重叠,材质数量等

  • 触发时机:当Canvas中的UI节点的Mesh改变时(SetActive,transform,颜色……..)

  • 触发过程:根据UI元素深度关系进行排序、检查UI元素的覆盖关系、检查UI元素材质并进行合批

  • 触发结果:重新Batch一次,无论当前Mesh的改变是否影响了父节点(也就是说一个很小的变化,就会让当前Canvas重新Batch一次)

  • 解决方案:

    1. 可以用多个同级Canvas或者Canvas套Cnavas的方法,来将复杂层级划分到不同Canvas中去,需要注意的是每个Canvas都至少有一个DrawCall(当有子UI元素时),这样可能会增加DrawCall
    2. 使用 动静Canvas分离的方案可以将ReBatch的范围限制在动态Canvas中
    3. 减少层级复杂度,少用嵌套的树形UI结构,同时将材质相同的UI尽量放到同一层级

1.2 Canvas Over-dirty, Re-batch次数过多

  • 每当UI元素的Mesh改变时,都会触发ReBatch来重新计算,因此我们要尽量减少UI元素Mesh的改变
  • 两个按钮中不叠加时,合批为2
  • 当第一个按钮文字和第二个按钮背景重叠时,合批为4

1.3 生成网格顶点时间过长

  • 可以看到Cumulative Vertex Count数量,越多耗时越久

1.4 片元利用率高 - Fill-rate overutilization

  • 一个像素被多次绘制,称为片元利用率高,一次绘制中,如果一个像素被反复绘制N次,这样会导致GPU利用率过高





六、使用Canvas的基本准则

  • 将所有可能打断合批的层移到最下边的图层,尽量避免UI元素出现重叠区域
  • 可以拆分使用多个同级或嵌套的Canvas来减少Canvas的Rebatch复杂度
  • 拆分动态和静态对象放到不同Canvas下。
  • 尽量不使用Layout组件
  • Canvas的RenderMode尽量Overlay模式,减少Camera调用的开销

七、Raycast优化

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

八、UI字体

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

  • 字体网格重建

    • UIText组件发生变化时
    • 父级对象发生变化时
    • UIText组件或其父对象enable/disable时
  • TrueTypeFontImporter

    • 支持TTF和OTF字体文件格式导入


  • 动态字体与字体图集

    • 运行时,根据UIText组件内容,动态生成字体图集,只会保存当前Actived状态的 UIText控件中的字符
    • 不同的字体库维护不同的Texture图集
    • 字体Size、大小写、粗体、斜体等各种风格都会保存在不同的字体图集中(有无必要,影响图集利用效率,一些利用不多的特殊字体可以采用图片代替或使用Custom Font,Font Assets Creater创建静态字体资源)
    • 当前Font Texture不包含UIText需要显示的字体时,当前Font Texture需要重建
    • 如果当前图集太小,系统也会尝试重建,并加入需要使用的字形,文字图集只增不减
    • 利用Font.RequestCharacterInTexture可以有效降低启动时间

九、UI控件优化注意事项

  • 不需要交互的UI元素一定要关闭Raycast Target选 项
  • 如果是较大的背景图的UI元素建议也要使用Sprite的九宫格拉伸处理,充分减小UI Sprite大小,提高UI Atlas图集利用率
  • 对于不可见的UI元素,一定不要使用材质的透明度控制显隐,因为那样UI网格依然在绘制,也不要采用active/deactive UI控件进行显隐,因为那样会带来gc和重建开销
  • 使用全屏的UI界面时,要注意隐藏其背后的所有内容,给GPU休息机会。
  • 在使用非全屏但模态对话框时,建议使用OnDemandRendering接口,对渲染进行降频。
  • 优化裁剪UI Shader,根据实际使用需求移除多余特性关键字。

十、滚动视图Scroll View优化

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

参考文章

https://zhuanlan.zhihu.com/p/343524911
https://zhuanlan.zhihu.com/p/343978391

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容