unity3d UI性能优化。

从UI(UGUI)上面的优化,我想从三个方向来分析:

drawcall的优化

动静分离的优化

文本,图片预选项的优化

三个优化,性能占比,从高到底。

一. drawcall的优化

    drawcall可以通过点开Stats和Window->Frame Debugger查看具体信息
    

    在进行drawcall优化的时候,我们可以通过,移动Frame Debug的左侧栏,然后观察drawcall数量的变化,从而找到那部分ui的drawcall数量不正常。

    具体的观察drawcall的方式讲了,下面来讲一下几个容易造成drawcall数量偏大的原因和优化drawcall的小tips

    1.mask的多次使用。

    mask对于drawcall的影响应该是所以组件里面最大的。每存在一个mask,就把mask以内和以外的UI分割成两个“世界”,依次计算两个“世界”的drawcall,然后再相加。原因是mask以内和以外的UI不能通过unity3d一次渲染(batch)。所以在使用mask的时候要仔细思考,能不用就不用,实在要用可以考虑用带通道的图片代替mask的遮罩功能。

    2.图集整理不规范。

    影响drawcall数量的根本是batch(批处理数),而batch是根本一个一个图集来进行批处理的。简单来说,两张image重叠在一起,当两张image的sprite是一个图集里的时候,这两张image就是一个batch;当不是一个图集的时候,两张image就变成了两个batch。所以在处理图集的时候,通常做法是,常用图片放在一个共有图集,然后独立界面的图片放在一个图集,一个UI最好控制在2-3个图集。

    3.图文交叉。

    unity3dUGUI的batch规则除了依赖于图集之外,还依赖于组件关系,当2张图片(同一图集),1个文字进行重叠时,处理不好会发生一些drawcall的多余。比如:image->image->text,这样的话,drawcall就是两个,但是当:image->text->image的时候,就算两张image的sprite是一个图集的,这样的drawcall都会有3个。所以尽量不要出现image->text->image,图文交叉的情况。根据原因2,也有个小tips,当存在两个图集的三张image的时候,也尽量不要出现image1->image2->image1这样的操作。

    4.UI层级的深度。

    在不必要的情况下,我们尽量减少UI层级的深度,在UGUI中Hierarchy面板,节点的的深度,表现的就是UI层级的深度,我们UI中有N层,N越大越靠前,会遮住后面的组件。当深度越深,不处在同一层级的UI就越多,drawcall就会越大。

二. 动静分离的优化

    当我们在制作UI的时候,我们应该考虑到整个UI,哪个部分处于经常变化的部分,哪个部分属于不常变化的部分。把常变化的归到动态区域,把不常变化的归到静态区域。

    以一个游戏的主界面为例:

    

    我把界面简单的规划成了4个区域:

    1.上方按钮区域

    2.右方按钮区域

    3.技能区域

    4.人物头像及任务区域

    如果按照简单的动静分离原因:1.2区域是不常变化的,我们放在一个节点以下;3.4区域是常变化的,几乎每一秒都在变化,我们放在一个节点以下。这样就可以达到动静分离的效果。

    动静分离,可以减少UIMesh动态更新,在某些比较复杂,常驻的界面可以这样优化。小的界面就没必要了,因为不必要的节点有可能会造成drawcall的增加的。

三. 文本,图片预选项的优化

    这部分主要有两个可以优化的点。效果可能没有前面两种优化大,但是积少成多,在项目后期,有优化瓶颈的时候,也是非常有必要的。

    1.image和text组件的Raycast Target属性

    在组件不需要射线检测的时候,我们可以尽可能的把射线检测去掉,在运行的时候,就可以减少不必要的性能开销。

    这里给一段小代码,在创建image和text的时候,就可以去掉Raycast Target

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;

public class CancelImgandTxtRay
{
    [MenuItem("GameObject/UI/Image WithoutRay", false, 10)]
    static void CreatImage(MenuCommand menuCommand)
    {
        EditorApplication.ExecuteMenuItem("GameObject/UI/Image");
        GameObject go = Selection.activeGameObject;
        GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
        go.GetComponent<Image>().raycastTarget = false;
    }

    [MenuItem("GameObject/UI/Text WithoutRay", false, 10)]
    static void CreatText(MenuCommand menuCommand)
    {
        EditorApplication.ExecuteMenuItem("GameObject/UI/Text");
        GameObject go = Selection.activeGameObject;
        GameObjectUtility.SetParentAndAlign(go, menuCommand.context as GameObject);
        go.GetComponent<Text>().raycastTarget = false;
    }
}

    2.text组件的Rich Text属性

    当text组件勾选了Rich Text的时候,其实每次文本显示都会先判断一下是否拥有这个属性,然后做正则匹配,如果不勾选的话,其实还是有一些优化的。但是这个优化点其实是最小的,不必要的话,其实没必要优化这个,事实证明,在通常情况下如果我们不勾选,但是后期又要对text进行富文本的操作,容易引出一些不必要的bug。

    第一条和第二条优化是必须的,带来的性能提升是巨大的。但是当不存在性能瓶颈的时候,不建议去优化第三条,性能的提升不是很大,容易引出不必要的bug,但是如果存在性能瓶颈,我就差这么一点了,那么可以去优化他,是可行的。

    以上个人一点愚见,仅供参考。

  • 18
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值