Q&A——资源管理(十四)

来源:互联网 发布:exec php 执行不了 编辑:程序博客网 时间:2024/06/16 05:19

资源管理

Q1:我的游戏运行一段时间之后,已经切换到一个空场景了,然后手动调用了System.GC.Collect(); Resources.UnloadUnusedAssets();为什么还是会有这么多贴图资源被引用呢。我猜可能是由于一些脚本中的静态变量引用导致,请问有办法查出来是哪些静态变量吗?

很大可能是这些资源直接或间接被其他Container缓存了,这种情况在我们进行内存泄露分析时经常遇到。如果是Unity 5.3以后版本,建议尝试在iOS版本上在Memory Profiler中进行查看具体的引用信息。


资源管理

Q2:在UWA性能测评报告中,为什么同样分辨率、同样格式的纹理资源,其内存相差一倍?表格中Mipmap的数量是怎么计算的?
请输入图片描述

一般来说,在开启Mipmap的情况下1024x1024的ETC2纹理应该是1.3MB的,但YYS_02_buildling002_2为2.7MB,所以很有可能是开启了Read/Write选项,建议在Editor中查看该纹理的具体设置。

Mipmap的数值表示该纹理Mipmap的层数,其与纹理的分辨率相关,具体建议阅读:https://en.wikipedia.org/wiki/Mipmap。

资源管理

Q3:关于资源冗余,我从AssetBundle中加载一张贴图后,即使Unload(false),是否还会在内存中保留一个没有被任何资源引用的贴图呢?是否非得UnloadUnusedAssets()才能把这个“僵尸”资源给卸载掉?

是的,从AssetBundle中加载资源并执行Unload(false)后,其加载出的资源如果没有被引用,那么会处于“游离”状态,即问题中所谓的“僵尸”资源。除Resources.UnloadUnusedAssets()外,Resources.UnloadAsset和AssetBundle.Unload(true)均可以将其进行卸载。

资源管理

Q4:请教Lightmap相关的优化问题。我现在的场景中有N个GameObject共用一个Prefab,烘培Lightmap时,会生成出N个Lightmap贴图。有没有办法把这些生成的Lightmap合成一张?

如果场景中某些物件在Lightmap纹理中占据的空间较大,但实际上并不需要较高的精度,那么可以选中该物体,并在Lighting面板的Object子面板中将其Scale in lightmap数值调低,从而可以降低其在Lightmap纹理中的空间,甚至减少Lightmap纹理的数量。

资源管理

Q5:Unity里的Shader能不能用关键字#ifdef #endif把整个pass包起来?

#ifdef 和 #endif 并不能写在Pass之外,如果有动态开关Pass的需求,可以通过Shader Lod来实现,即设置两个Level不同的SubShader分别包含1个和2个Pass,直接通过改变该Shader的局部Lod值,即可实现SubShader的切换。关于Shader Lod的细节,可见官方文档:
http://docs.unity3d.com/Manual/SL-ShaderLOD.html

资源管理

Q6:我把多个AssetBundle打成一个大包,会出现部分粒子特效贴图丢失的问题。参数设置为CollectDependencies | DeterministicAssetBundle | UncompressedAssetBundle时,贴图是对的,但是脚本、Shader又出错了。由于Unity 4.x下AssetBundle的问题比较多,想知道打大包可行性如何?

在Unity 4.x的版本中我们并不建议将资源打成一个超大的AssetBundle包,一般情况下,单独发布的AssetBundle文件应尽可能小于1MB。这主要是因为Unity 4.x版本中AssetBundle文件压缩格式为LZMA格式,而不是LZ4格式(Unity5.3版本以后推荐格式)。所以,如果一个AssetBundle文件较大,则在加载时很可能会出现较高的WebStream占用,从而造成项目运行时局部时刻内存过高的情况,进而影响运行的稳定性。

同时,需要说明的是,Unity 4.x版本在制作AssetBundle文件时,应尽可能开启CollectDependencies | CompleteAssets | DeterministicAssetBundle选项。如果开启后出现资源丢失,则一般是由于依赖关系所致,相关资源被打包到其他AssetBundle文件中。对此,我们建议在UWA资源检测的结果中,查看所丢失的资源是否存在于AssetBundle中,以及存在具体哪个AssetBundle文件中,从而来进一步解决AssetBundle的打包正确性问题。
请输入图片描述

资源管理

Q7:我们的游戏中,相邻关卡资源很相似。现在涉及到切换场景,每次都要卸载资源又加载资源,很耗时;但是如果先加载再卸载,内存峰值又会涨。请问UWA有什么建议么?

UWA建议研发团队可以将共用资源剥离出来,与其他场景进行依赖关系打包。这样当相邻副本切换时,其共用资源常驻内存,可以避免频繁加载和卸载所带来开销。如果研发团队想更准确地定位到底是哪些资源在频繁加载和卸载,那么可以通过UWA性能报告中的“资源管理”界面进行查看。如下图所示,多种不同资源被不同场景所共用,存在频繁加载和卸载的情况。对此,建议研发团队在内存允许的情况下,将此类资源进行缓存。

0.png


资源管理

Q8:在AssetBundle打包的时候,我们是一个文件一个AssetBundle,基本不存在冗余的情况了。但这种做法是否可取?UWA有什么建议?

这种做法是不足取的,因为这会造成Assetbundle文件非常细碎,进而带来两点不足:
(1)加载IO次数过多,从而增大了硬件设备耗能和发热的压力;
(2)在我们测试过的Unity 5.3 ~ 5.5 版本中,Android平台上在不Unload的情况下,每个AssetBundle的加载,其每个文件的SerializedFile内存占用均为512KB(远高于其他平台),所以当内存中贮存了大量AssetBundle时,其SerializedFile的内存占用将会非常巨大。

下图为我们获取的游戏运行时AssetBundle在内存中的贮存数量,在某一副本中,AssetBundle可以达到160个,那么其在Android设备上的SerializedFile内存也将达到80MB。该问题为目前Unity项目开发团队特别需要注意的地方。

请输入图片描述


资源管理

Q9:BuildAssetBundleOptions.DisableWriteTypeTree这个选项的实际用处是什么?

在Unity 5.x版本中,AssetBundle在制作时会默认写入TypeTree信息,这样做的好处是可以保证AssetBundle文件的向下兼容性,即高版本可以支持以前低版本制作的AssetBundle文件。所以,如果开启DisableWriteTypeTree选项,则可能造成AssetBundle对Unity版本的兼容问题,虽然关闭TypeTree会使Bundle更小,但我们一般都不建议研发团队在制作AssetBundle文件时开启该选项。


资源管理

Q10:我用DestroyImmediate 和 Resource.Unload 来进行卸载Prefab,在卸载前我获取Prefab下所有的材质,发现有些文件无法卸载,类似下图中的MangedStaticReferences(),怎么卸载这些资源呢?

请输入图片描述

从图片上来看,这个是资源被逻辑代码缓存的问题。图中YangCheng纹理之所以无法卸载,是因为它被YangCheng材质所引用,而YangCheng材质又被UIAtlas脚本所引用,ManagedStaticReferences表示此资源最终是被逻辑脚本所引用,即可能某个脚本中的变量或者Container对其仍有索引。从该图来看,很可能是使用到该Texture的某个UI GameObeject没有被释放所致。建议研发团队可以检测一下具体使用YangCheng材质的索引情况,定位其被索引的原因。一般主要有两种可能,一是它自己本身被储存于脚本变量中,二是引用它的GameObject被储存于变量中。研发团队可先从以上两方面入手,对该资源进行检测和排查。


0 0