Ugui优化

1.DrawCall

1-1.什么是DrawCall:
CPU调用命令GPU进行渲染的操作。
1-2..CPU和GPU并行工作的原理:
CPU和GPU并行工作依赖一个东西:命令缓冲区(Command Buffer)。命令缓冲区包含了一个命令队列,由CPU向其中添加命令,而由GPU从中读取命令。添加和读取的过程是相互独立的,因此命令缓冲区可以使CPU和GPU相互独立工作。当CPU需要渲染一些对象时,它可以向命令缓冲区添加命令,而GPU完成了上一次的渲染任务后,它就可以从命令队列里取出一个命令并执行它。
1-3.为什么要优化DrawCall?
CPU处理提交drawCall的操作是串行的,大量的提交零散的DrawCall,GPU在提交的DrawCall队列里可以多次处理多个DrawCall。而GPU渲染的并行速度是很快的,大量的DrawCall会导致GPU等待CPU。优化DrawCall可以让CPU与GPU的执行效率增大。

2.Ugui的DrawCall

2-1.Ugui的DrawCall与画布排序原则
Ugui画布排序是按类型排序的,只要两种UI元素不发生重叠,Ugui会自动按类型合并DrawCall,在界面设计与UI原型设计时应该避免多个UI元素重叠的问题,这样可减少后期的优化压力。
Mask组件
Mask组件基于模板缓存制作的。一个Mask组件会产生4个DrawCall
一、RectMask2D
RectMask2D不需要依赖一个Image组件,其裁剪区域就是它的RectTransform的rect大小。

性质1:RectMask2D节点下的所有孩子都不能与外界UI节点合批且多个RectMask2D之间不能合批。
性质2:计算depth的时候,所有的RectMask2D都按一般UI节点看待,只是它没有CanvasRenderer组件,不能看做任何UI控件的bottomUI。
二、Mask
Mask组件需要依赖一个Image组件,裁剪区域就是Image的大小。

性质1:Mask会在首尾(首=Mask节点,尾=Mask节点下的孩子遍历完后)多出两个drawcall,多个Mask间如果符合合批条件这两个drawcall可以对应合批(mask1 的首 和 mask2 的首合;mask1 的尾 和 mask2 的尾合。首尾不能合)
性质2:计算depth的时候,当遍历到一个Mask的首,把它当做一个不可合批的UI节点看待,但注意可以作为其孩子UI节点的bottomUI。
性质3:Mask内的UI节点和非Mask外的UI节点不能合批,但多个Mask内的UI节点间如果符合合批条件,可以合批。
从Mask的性质3可以看出,并不是Mask越多越不好,因为Mask间是可以合批的。得出以下结论:
当一个界面只有一个mask,那么,RectMask2D 优于 Mask
当有两个mask,那么,两者差不多。
当 大于两个mask,那么,Mask 优于 RectMask2D。

2-2合并图集
注意动态加载的图与模块相关的图分离。太大的图集不在动态加载行列产生内存浪费。这些可根据自己的策略做选择。
2-3动静分离
这里指的是所有的UI资源,包括元素,图片,图集等。
这里优化点有两个:
1.Canvas.BuildBatch
2.Canvas.SendWillRenderCanvases

优化网格重建
一般把动态的元素放在一个Canvas里,没有动态效果的静态元素放在Canvas。移动位置,缩放大小,这些都会触发网格重建。

但是如果只是非常大量的动态元素,每个挂载Canvas是会产生大量的DrawCall,可以考虑使用代码动态挂载Canvas。达到动静分离的目的,不需要时再删除Canvas。
UI上全用Image 的Color属性,会直接修改UI网格的顶点颜色属性,会触发网格重建。所以这里我们可以给image加入一个材质,直接修改这个材质上的color属性。这个不会直接修改顶点属性。不会触发网格重建,从而达到优化目的。
避免使用OutLine,Shadow组件。使用Text Mesh Pro代替
避免频繁使UI元素SetActive(开、关),会造成网格重建,考虑使用CanvasGroup。

3.OverDrall

*这个模块的优化,遵循的原则是,重叠的元素越少,越不容易产生OverDrall。
3-1.Image相关优化
3-1-1Image组件使用Image Type为Sliced:去掉Image的 Fill Center模式(九宫格),可以镂空一些UI元素的中间不需要拉伸的区域,可以减少OverDrall的产生。
3-1-2 Image组件使用Image Type为Slimple:复杂的图案,中间或者边上有很多透明区域的图,可以使用Use Sprite Mesh这个选项。打上勾,可以按网格方式渲染图片,牺牲内存来优化这部分OverDrall。(unity2017以上版本才有此功能,以下版本可以网上参考实现的代码)
3-1-3 使用Image组件接收Ugui点击事件,实现界面事件的方式。Image只要打开,不管设置的图片是否为空,依然会产生OverDrall。如果在项目中存在大量的这种元素。优化的作用还是可观的。建议继承unity类来解决。
可以参考钱康来写的如下代码:

    using UnityEngine;
    using System.Collections;
     
    namespace UnityEngine.UI
    {
        public class Empty4Raycast : MaskableGraphic
        {
            protected Empty4Raycast()
            {
                useLegacyMeshGeneration = false;
            }
            protected override void OnPopulateMesh(VertexHelper toFill)
            {
                toFill.Clear();
            }
        }
    }

4.减少CPU耗时

减少Raycast Target

Raycast Target即使在你没使用时,依然会产生CPU计算。这样的东西是没必要的,虽然一个这样的计算微乎其微。但是优化的东西,就是一点点积累的。--不以善小而不为,不以恶小而为之。这里建议在项目前期就加入去除Raycast Target工具,这里可以参考我的另一个文章:Ugui创建组件去除RaycastTarget 属性
如果项目到达中期,那就借助工具优化吧:RaycastTarget检测小工具

你可能感兴趣的:(Ugui优化)