yukamu 发表于 2022-3-10 09:07

Unity性能优化基础篇——UI优化小技巧

UI的性能问题是很多人容易忽视,但却很重要的一个问题。通常我们的UI界面可能是美术或者策划来拼接,然后程序在做功能时并不会去关心UI的布局是否合理,有没有动静分离,以及禁用一些不需要的属性。所以在团队中制定一些做UI的规则就很重要。
1,避免频繁调用GameObject.SetActive
如果你隐藏一个较大的UI界面,下面有很多子节点,也会有很大的开销,我们可以通过Profiler看下耗时Time ms高达7.3


解决办法可以对频繁切换激活状态的UI采用平移出屏幕、修改Layer等方式来替换。
另外也不要对Canvas做频繁的Enable操作,重新激活Canvas以及它的子Canvas,会执行重新构建(Rebuild) 以及重新批处理(Rebatch)操作
2,去掉Image的Raycast Targe
UGUI的Image组件的RaycastTarget勾选以后会消耗一些效率,为了节省效率就不要勾选它了,不仅Image组件Text组件也是这样。
一般UI里也就是按钮才需要接收响应事件,那么大部分image和text是是不需要开RaycastTarget的
所以可以重写Create->UI->Image的事件,这样创建出来的Image就不带RaycastTarget了
      
      static void CreatImage()
      {
            GameObject go = new GameObject("Image", typeof(Image));
            go.GetComponent<Image>().raycastTarget = false;
            if (Selection.activeTransform)
            {
                if (Selection.activeTransform.GetComponentInParent<Canvas>())
                {
                  go.transform.SetParent(Selection.activeTransform);
                }
            }
            else
            {
                Transform p = FindObjectOfType<Canvas>().transform;
                if (p != null)
                {
                  go.transform.SetParent(p);
                }
            }
      }

3,Mask换Rect Mask 2D
这个在DrawCall的文章中说,Mask会影响合批,而Rect Mask 2D 则不会,但是Rect Mask 2D 只支持矩形。
我分享一个可以随心所欲使用各种形状Mask的插件
使用方法:画地为Mask,随心所欲的高效遮罩组件 - 立航 - 博客园
4,UI的布局
UI的布局层级不要太深入,要动静分离,可活动的元素放在一个Canvas下,不可活动的元素放在另一个Canvas下。虽然两个Canvas打断了合批,但是却减少了网格的重建时间,总体上是有优化的,所以一般建议每个较复杂的UI界面,都自成一个Canvas(可以是子Canvas),在UI界面很复杂时,甚至要划分更多的子Canvas。但是,Canvas又不能细分的太多,因为会导致Draw Call的上升。
5,不要把image button作为点击
很多人在创建button时用很多不可见的Image作为交互响应的控件,这些image虽然被alpha被设置为0不可见,但是DrawCall依然存在
解决办法实现一个只在逻辑上响应Raycast但是不参与绘制的组件即可
using UnityEngine;

using System.Collections;

namespace UnityEngine.UI

{

    public class Empty4Raycast : MaskableGraphic

    {

      protected Empty4Raycast()

      {

            useLegacyMeshGeneration = false;

      }

      protected override void OnPopulateMesh(VertexHelper toFill)

      {

            toFill.Clear();

      }

    }

}
6,优化-Overdraw
当有图片叠加在一起的时候,颜色会变深,这时就产生了Overdraw,越亮的区域表示overdraw的程度越高,也就越消耗GPU,Overdraw无法避免,只能优化降低



查看Overdraw


[*]过大的不必要绘制尽量代码实现,例如点击屏幕空白区域返回功能,加透明image会增加很多,如果需要点击屏幕空白区域返回的功能,请看上一条有实现方法
[*]UI设计上尽可能简单减少重叠
[*]尽量减小过度绘制区域:实在需要多层绘制的地方,要尽量减小各部分过度绘制区域,使重合区域小,绘制的像素点也就少一点
[*]Unity的Mask组件会增加一层Overdraw,还会打断合批增加DrawCall(万恶的Mask),解解决办法参考前面说的第三条。
[*]对于slide九宫格图片,可以看情况取消fill center属性,那样中心区域会不渲染,中心区域也就镂空,重合面积也会小
[*]无用的Image,少量的panel或者单纯的空父物体身上加着image,虽然没有给图片,但是还是会渲染
分享一个减少OverDraw脚本PolygonImage: https://github.com/jojohello/Unity_PolygonImage
Overdraw优化参考资料:优化-Overdraw
关于UGUI的优化参考资料:关于Unity中的UGUI优化,你可能遇到这些问题 - UWA Blog
Unity 之 UGUI优化(Optimizing UGUI)---当最专业的拖拖拽拽
页: [1]
查看完整版本: Unity性能优化基础篇——UI优化小技巧