优化-Overdraw
问题:GPU Overdraw局部像素区域压力过大
image.png
1.Overdraw
在某个背景上有个按钮,要将按钮绘制在背景上,这个就是Overdraw,Overdraw无法避免,只能优化降低
2.性能参数
- 总填充数值峰:单帧总填充像素数量最大值
- 填充倍数峰值:单帧最大填充倍数(10.0X就是该帧刷新10遍)
- 单帧填充倍数:该帧总填充数/该帧渲染相机分辨率
3.优化方案
- 控制绘制顺序:PC上资源无限,一般都是从后往前绘制,但在移动上,尽量从前往后绘制.在Unity中,那些Shader中被设置为“Geometry”队列的对象总是从前往后绘制的,而其他固定队列(如“Transparent”“Overla”等)的物体,则都是从后往前绘制的。这意味这,我们可以尽量把物体的队列设置为“Geometry” 。
- 尽量减小过度绘制区域:实在需要多层绘制的地方,要尽量减小各部分过度绘制区域,使重合区域小,绘制的像素点也就少一点
- 注意性能与效果的取舍:UGUI的许多控件有很好的通用性和展示效果,但是可能会耗更多性能
- 过大的不必要绘制尽量代码实现:例如点击屏幕空白区域返回功能,加透明image会增加很多
- UI设计上尽可能简单减少重叠
4.针对性优化
图1.png
1)文字部分
主要原因是使用了Outline,Outline实现方式是将Text的四个顶点传过去复制四份,设置四份偏移量实现效果,将偏移量设置很大之后,可以看到一个Text周围有四个相同的Text
//Outline源码
public class Outline : Shadow
{
protected Outline()
{}
public override void ModifyVertices(List<UIVertex> verts)
{
if (!IsActive())
return;
var start = 0;
var end = verts.Count;
ApplyShadow(verts, effectColor, start, verts.Count, effectDistance.x, effectDistance.y);
start = end;
end = verts.Count;
ApplyShadow(verts, effectColor, start, verts.Count, effectDistance.x, -effectDistance.y);
start = end;
end = verts.Count;
ApplyShadow(verts, effectColor, start, verts.Count, -effectDistance.x, effectDistance.y);
start = end;
end = verts.Count;
ApplyShadow(verts, effectColor, start, verts.Count, -effectDistance.x, -effectDistance.y);
}
}
//ApplyShadow源码
protected void ApplyShadow(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
{
UIVertex vt;
var neededCpacity = verts.Count * 2;
if (verts.Capacity < neededCpacity)
verts.Capacity = neededCpacity;
for (int i = start; i < end; ++i)
{
vt = verts[i];
verts.Add(vt);
Vector3 v = vt.position;
v.x += x;
v.y += y;
vt.position = v;
var newColor = color;
if (m_UseGraphicAlpha)
newColor.a = (byte)((newColor.a * verts[i].color.a) / 255);
vt.color = newColor;
verts[i] = vt;
}
}
解决方案:
1.不使用或者使用Shadow(Shadow通过为图像或者文字的Mesh添加顶点实现阴影效果,Outline继承Shadow,在对象四个角上各添加一个Shadow)
2.使用Textmesh Pro(Unity5.5)需要制作相应的字体文件,对于动态生成的文字效果不好,固定字体很好
(https://blog.csdn.net/dark00800/article/details/73011343?utm_source=itdadao&utm_medium=referral)
3.修改Mesh的UV坐标,提取文字原始UV坐标,扩大文字绘图区域,对文字纹理周围像素点采样,新旧颜色融合
(http://gad.qq.com/article/detail/29266)
2)适配IphoneX
适配的需要加了层背景,不是iPhoneX失活就可以
3)背景人物mesh
裁剪小一点更好
图1改.png
图2
1)Mask组件
Unity的Mask组件会增加一层Overdraw,还会多增加4个DrawCall
解决:
1.使用RectMask2D代替,缺点是只能用于矩形
2.对于多边形,用MeshMask,红色为UnityMask,蓝色是MeshMask,UnityMask消耗15个DrawCall,Overdraw2次,MeshMask消耗1个DrawCall,1层OverDraw(https://www.cnblogs.com/leoin2012/p/6822859.html)
image.png
image.png
2)Image的slide属性
对于slide九宫格图片,可以看情况取消fill center属性,那样中心区域会不渲染,中心区域也就镂空,重合面积也会小
图2改.png
图3
1)重合多的地方尽可能不重合
image.png
2)无用的Image
少量的panel或者单纯的空父物体身上加着image,虽然没有给图片,但是还是会渲染
3)移动的波浪图片过大过多(修改高度,宽度)
4)特效粒子效果优化(http://www.u3dnotes.com/archives/807)
粒子效果薄弱的可以使用序列帧动画实现
图3改
图4
1)三层大底图,一个纯黑底,还有两层楼梯背景(可以纯黑底图合并到两层)
2)楼梯前底图可以小一点不和最底下图标重叠
image.png
图4改
图5
1)粒子效果
部分小细节:
1.slide九宫格图片,取消fill center,中心镂空
2.mask尽量不用,可以用rect mask2D 代替
3.不用UI/Effect,包括Shadow,Outline,Position As UV1
4.不用Image的Tiled类型
5.不用Pixel Perfect
6.动静分离,动态的在父物体上加个Canvas
7.尽量active,不要destroy,也不要设置Alpha=0这样还是会渲染
8.不用BestFit(代价高,Unity会为该元素用到的所有字号生成图元保存在Altlas中,增加额外生成时间,还会使得字体对应的atlas变大)
9.特效粒子
作者:叫我颜先生
链接:https://www.jianshu.com/p/7167c516bd75
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
上一篇: 设计模式中的原型模式在Python程序中的应用示例
下一篇: 吃苹果对止咳很有帮助