Unity技术分享(84)|异步纹理加载|多维材质|内存...

原文链接:https://blog.uwa4d.com/archives/TechSharing_84.html

我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
UWA QQ群:465082844
UWA 问答社区:answer.uwa4d.com


内存

Q1:在UWA的测评结果中,我们的Mesh文件内存过高(使用UWA GOT测试最大的场景会达到200MB),大部分是由于场景的物件导致的。我们的场景物件是这样加载的:场景有一个基础的框架(地面、天空盒和个别大的物件等),在进入场景后,会根据位置来加载其他的物件,加载的物件在离开视野后,为了防止下次再加载,只将其隐藏了,并没有销毁,这样的话,人物如果在场景里跑了一圈,就相当于整个场景的物件,都会进入内存。请问,是不是将离开视野的场景物件销毁比较好呢,销毁后是不是要调用UnloadUnusedAssets才能彻底从内存中去除呢?

如果题主做的是移动游戏,那么200MB确实太大了。
建议题主建立一个Memory Pool来缓存场景中的物体,至少有以下两个规则:
(1)Pool必须有一个上限,一般为容器的数量,超过最大阈值后即开始进行清理;
(2)为Pool中每个Object记录一个存储时间,当时间超过一定阈值后进行清理,或者当Pool满了后,将时间最长的进行Deactive Object进行清理。

通过缓存池来进行销毁较长时间不再显示的的物体,同时,可以通过UnloadAsset API来卸载相关的资源,Resources.UnloadUnusedAssets API一般只建议在场景切换处进行使用。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59f2da210558dee424da9d69


加载

Q2:Unity版本:5.6.1f1,如果使用Static Splash Image , 一张1000×500的图大约会占用30MB~40MB的内存(PSS值变化),并且这个内存没有释放的迹象,感觉像是个Bug。

我们对这个问题进行了测试,看上去这个问题是Unity 5.6.1的Bug,在5.6.2版本中应该已经被修复了。下面是我们的测试方式:

Unity测试版本:Unity 5.6.2
测试设备:红米4X
测试步骤:
1、当没有加入Splash Image 时,空场景项目加载后,其PSS内存占用情况如下图所示:


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第1张图片

2、项目中放入如下的24MB Splash Image。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第2张图片

3、当纹理不压缩时,其项目启动后,PSS内存确实明显上涨了,由之前的51796KB上升到85747KB。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第3张图片

但仅过一小段时间(<30s),PSS内存就降下去了,回落到52083KB,可见原来较大的Splash Image已经被释放。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第4张图片

我们在该设备上进行了多次测试,均得到类似的结果。对此,我们的建议如下:
(1)尝试升级Unity引擎,在Unity5.6.2以上版本中进行测试,看是否还会出现PSS内存不回落现象;
(2)尝试在其他设备上进行测试,查看是否是特定设备带来的内存问题。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59f1d1414bcaad4150f9e5bb


性能

Q3:异步纹理加载Asynchronous Texture Upload这个功能最后到底有没有实用?

Unity技术分享(84)|异步纹理加载|多维材质|内存..._第5张图片

就是这个东西,按理应该是解决异步加载时,纹理却只能同步加载的问题,现在界面上也一直有这设置,但我翻到网上介绍的时候看到如下信息:

Unity技术分享(84)|异步纹理加载|多维材质|内存..._第6张图片

这个是默认就开启的,只是得开启多线程渲染才有效,因为要在 Render Thread 里上传纹理,还有文档里提到的各种限制,比如只针对关闭了 Read/Write 的纹理… 非多线程渲染时,异步加载纹理的时候,可以在 Loading.UpdatePreLoading 这个函数里看到较高的 Texture.AwakeFromLoad。但多线程渲染时,这部分的开销就会变得很小,因为这部分开销被放到 Render Thread 去了,如下图中的 Gfx.UploadTexture。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第7张图片

但需要注意的是,这个地方的异步并不是流式的加载,也就是说,当加载一个大纹理的时候,还是一次性完成的,并不会分帧去做,如下图加载了一张2048的纹理,图中绿色峰值是Gfx.WaitForPresent,也就是主线程在等待 Render Thread。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第8张图片

综上,这个功能实际上就是把某些满足要求的纹理的加载时间从主线程移到了渲染线程。在某些情况下,确实是可以提高总体的加载速度的。但这个功能并不能真正地“解决异步加载时纹理却只能同步加载”的问题,只是把卡顿放到渲染线程去了(如果耗时高了,主线程还是要等的)。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59f07256d4035ac353374454


性能

Q4:在目前的Unity版本中,使用多维材质是否会对效率产生影响,用多维材质和把模型分块哪个更好?

制作美术资源时,应该尽量避免使用多维材质。先举例说明多维材质的一个优点是拆分模型做不到的: 一块大石头有石头和草地两个材质,做成一个整体的模型,使用多维材质,作为一个物件进行烘焙,在Lightmap上的UV分布是一个整体,不会出现拆分为两个模型烘焙产生的接缝问题。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第9张图片

除了上面这种情况,其他情况下推荐将模型拆分成多个模型赋予不同的材质。
优点是:
1、多个模型会作为多个MeshObject参与到裁剪、静态批次等优化中 ;
2、拆分的模型和贴图可以进行材质合并,程序才能进行下一步的优化,如果本身是多维材质,就无法进行合并DrawCall的优化;

第一个优点就能带来很大的收益。制作上应该按照一个模型对应一个贴图的做法进行,如果模型是一个整体,比如房子由底座、墙体、屋顶组成,建议将他们多选导出成一个FBX。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第10张图片

另外,不同材质的模型建议做成多个模型,再多选导出成一个FBX,仍然是一个模型对应一个贴图的规范进行制作。


Unity技术分享(84)|异步纹理加载|多维材质|内存..._第11张图片

该问题来自UWA问答社区,感谢文雅提供了回答,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/59e890dbe02a95cc6d0c4987


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

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:465082844(仅限技术交流)

你可能感兴趣的:(Unity技术分享(84)|异步纹理加载|多维材质|内存...)