从UI(UGUI)上面的优化,我想从三个方向来分析:
drawcall的优化
动静分离的优化
三个优化,性能占比,从高到底。
具体的观察drawcall的方式讲了,下面来讲一下几个容易造成drawcall数量偏大的原因和优化drawcall的小tips
mask对于drawcall的影响应该是所以组件里面最大的。每存在一个mask,就把mask以内和以外的UI分割成两个“世界”,依次计算两个“世界”的drawcall,然后再相加。原因是mask以内和以外的UI不能通过unity3d一次渲染(batch)。所以在使用mask的时候要仔细思考,能不用就不用,实在要用可以考虑用带通道的图片代替mask的遮罩功能。
影响drawcall数量的根本是batch(批处理数),而batch是根本一个一个图集来进行批处理的。简单来说,两张image重叠在一起,当两张image的sprite是一个图集里的时候,这两张image就是一个batch;当不是一个图集的时候,两张image就变成了两个batch。所以在处理图集的时候,通常做法是,常用图片放在一个共有图集,然后独立界面的图片放在一个图集,一个UI最好控制在2-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这样的操作。
在不必要的情况下,我们尽量减少UI层级的深度,在UGUI中Hierarchy面板,节点的的深度,表现的就是UI层级的深度,我们UI中有N层,N越大越靠前,会遮住后面的组件。当深度越深,不处在同一层级的UI就越多,drawcall就会越大。
以一个游戏的主界面为例:
我把界面简单的规划成了4个区域:
1.上方按钮区域
2.右方按钮区域
3.技能区域
4.人物头像及任务区域
如果按照简单的动静分离原因:1.2区域是不常变化的,我们放在一个节点以下;3.4区域是常变化的,几乎每一秒都在变化,我们放在一个节点以下。这样就可以达到动静分离的效果。
动静分离,可以减少UIMesh动态更新,在某些比较复杂,常驻的界面可以这样优化。小的界面就没必要了,因为不必要的节点有可能会造成drawcall的增加的。
三. 文本,图片预选项的优化
在组件不需要射线检测的时候,我们可以尽可能的把射线检测去掉,在运行的时候,就可以减少不必要的性能开销。
这里给一段小代码,在创建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().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().raycastTarget = false;
}
}
当text组件勾选了Rich Text的时候,其实每次文本显示都会先判断一下是否拥有这个属性,然后做正则匹配,如果不勾选的话,其实还是有一些优化的。但是这个优化点其实是最小的,不必要的话,其实没必要优化这个,事实证明,在通常情况下如果我们不勾选,但是后期又要对text进行富文本的操作,容易引出一些不必要的bug。
第一条和第二条优化是必须的,带来的性能提升是巨大的。但是当不存在性能瓶颈的时候,不建议去优化第三条,性能的提升不是很大,容易引出不必要的bug,但是如果存在性能瓶颈,我就差这么一点了,那么可以去优化他,是可行的。
以上个人一点愚见,仅供参考。