如何优化Shader.Parse的调用频率?

如何优化Shader.Parse的调用频率?

本期聚集话题:优化Shader.Parse的调用频率、模型导入Mesh Compression设置、Static Batching对DrawCall的影响...


这是第117篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)


性能优化

Q1:我的UWA性能测评报告中反馈Shader.Parse调用过多,改了多次没什么起色,请问该如何优化?
2520(0).png
我先说下我的方案:
1)先将所有资源依赖的Shader按文件夹进行AssetBundle打包;
请输入图片描述

2)在加载时加载依赖的Shader AssetBundle,解析后保存不释放;
请输入图片描述
请输入图片描述
理论上每个Shader只会加载一次,并且缓存不再释放了的,但是在切换场景的时候还会有Shader.Parse调用,这是为什么呢?
请输入图片描述

题主的情况存在以下两种可能:
(1)大概率情况:AssetBundle中Shader存在冗余现象,推荐通过UWA线上资源检测服务,去查看你们的AssetBundle中Shader是否有冗余;
(2)小概率情况:Shader在使用时动态加入了额外的Keyword,从而造成一些CreateGPUProgram的开销。
以上都有可能,建议题主先通过以上两点进行检测。
另外,我看到在题主的代码中调用了大量的WarmupAllShaders这个API,它的开销其实很大,并且每次加载Shader后都调用会造成大量的重复解析浪费,建议后续通过ShaderVariantCollection.warmup API来代替。
具体的性能比较我们在之前的UWA Day 2018上有划过重点,以下是加载一个较大地形所用Shader时的相关性能比较。
请输入图片描述
请输入图片描述
请输入图片描述
至于如何使用ShaderVariantCollection.warmup,题主可自行查看Unity文档,不难。

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b2cb1be2a66cc14117db59e


资源管理

Q2:官方文档中对于Instance ID的定义是这样的:
“The instance id of an object is always guaranteed to be unique.”

那么按理说一个Sprite资源,在游戏中它的Instance ID是唯一的。
但我在测试时发现一个奇怪的问题。

请输入图片描述
请输入图片描述
这里是打印Image中Sprite的Instance ID,跟我在资源文件中选中该图片,Inspector中Debug模式下显示的Instance ID不一致。
请输入图片描述
后面我又打印了Image对应的Sprite的GUID,与.meta文件中的GUID是对应得上的,所以不是很理解为什么Instance ID不一致。

题主你好,这里我是这样理解的:你在代码里面获取到的Instance ID和在Inspector中查看的图片的Instance ID所归属的对象,不是一个实例。也就是说,Instance ID的唯一性是针对对象实例的,而不是具体的资源。
例如,工程中的Prefab文件的Instance ID和它在场景中的实例化对象的Instance ID,也是不一样的。

感谢张锐@UWA问答社区提供了回答,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b2b6a052a66cc14117db591


资源管理

Q3:3D模型导入的时候,Mesh Compression的设置最终是导致什么效果?看了下Unity的文档说明,好像只是对Mesh的存储做了压缩优化,带来的直接受益是包体小了,但是也容易导致一些模型走样变形。

那么我有如下这些疑问:
1)加载的时候会不会因为压缩反而更慢了?还是压缩完之后加载到Mesh初始化出来的速度更快了(毕竟包小了)?
2)这个开启对运行时的性能优化有帮助吗?
3)这个开关会影响法线的效果吗?
4)这个选项大大们建议开启吗?

UWA:回答如下:
1)加载速度上差异应该是不大的,因为只是数值上的精度位数减少了;另外Mesh本身如果不是非常大,加载速度是很快的。所以加载上的差异应该是不需要太关注的。
2)根据文档,无论开不开Compression,加载完之后就是一样的内存占用了,所以运行时的性能上也不应该会产生差异。
3)法线部分会不会被压缩确实不好说,要结合具体项目来看。
4)这个选项要不要开是需要看模型本身的,只要美术同学觉得视觉上可以接受,那么Compression肯定是选得越高越好的。

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b2bb8b52a66cc14117db598


渲染

Q4:我在UWA博客上看到这个问答,有点疑惑,为什么Static Batching不影响DrawCall数?
请输入图片描述

这个截图中的问题有点老了。从现在往回看,准确地说,是Unity 5.0~5.3版本中,Static Batching是不影响Graphics Driver中的Draw Call次数的,这是因为在这些版本中,Unity并不会去像4.x中那样会动态合批index buffer。这点我们在今年的UWA Day上有过详细解释。
请输入图片描述
但在Unity 5.4版本之后,Draw Call合批操作又改回来了,和之前的4.x一样了,所以大家目前在使用Unity5.5、5.6和2017以后版本时,Draw Call在Static Batching后是会改变的。

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b2a32a52a66cc14117db575


代码

Q5:子类有没有办法让父类的序列化字段不显示在Inspector中?注:父类字段不是virtul。

PropertyAttribute应该可以实现,思路大致是:PropertyDrawer在OnGUI的时候判断SerializedObject的类型,如果是父类才进行真正的绘制。

感谢张迪@UWA问答社区提供了回答,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5b28737809749726e4188ed8

今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(原群已满员)

封面图片来自网络