AssetBundle 遇到的问题记录

来源:互联网 发布:2017淘宝流量突然下降 编辑:程序博客网 时间:2024/06/05 11:07

注意事项:

1.AssetBundle加载出来的Asset必须没有任何引用,否则即使AssetBundle卸载了,其Asset以及引用的纹理依然卸载不了。
2.AssetBundle本身被多个引用,只要其中一个调用卸载API即可。
3.纹理AssetBundle被依赖后加载,需要手动卸载纹理AssetBundle才能卸载纹理资源,比如删除实例化对象的时候置空所有的纹理的引用。
4.保持AssetBundle加载出来的Asset的所有的引用都是局部变量,这样可以利用局部作用域的原理对引用置空。
5.UGUI图集的AB卸载不干净的原因就一个:就是引用没有清理干净,删除实例化的对象之前先把Texture的引用置空,没有的删除的对象如果对纹理有占用,当然是清理不掉啦!


流程:

1.先删除实例化的对象(置空所有Texture的引用方便卸载图集的AB);
2.后置空所有对AssetBundle.Load出来的Asset的应用
3.再调用AssetBundle.UnLoad(false)

4.最后调用Resources.UnloadUnusedAssets();



Q10:将Shader独立打包,如果我在启动游戏的时候加载一次,那么之后切换场景是不是就不用每次都加载了?

确切地说,要达到后续Shader都不出现加载开销,需要满足以下两个条件:
(1)包含Shader的AssetBundle文件常驻内存;
(2)Shader已经全Load加载好;

只要满足这两个条件,后续加载好的GameObject,但凡依赖于这些Shader的,都会直接拿来进行使用,而不会再有加载和解析开销。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q1:字体作为多个资源的依赖包,会在游戏中被加载多次。我们现在有个问题,AssetBundle A资源依赖于这个字体,加载A的时候加载了一份字体,然后B资源也依赖这字体,而后加载B的时候我们没有去重复加载字体,这时候发现B资源上出现了字体丢失的现象。

请问加载资源的时候,Unity会自动去识别内存里是否有它的资源依赖包吗?如果有的话,为什么B加载的时候找不到已经存在内存中的字体?这里需要手动去做些什么处理吗?

同时我发现依赖包资源如果进行了bundle.m_AssetBundle.Unload(false)以后,其他依赖于这个包的资源就引用不到了。我们流程上对于每个读进来的AssetBundle,都会加载完后马上进行Unload(false),请问如果是依赖包的话,是不是不能对其进行这步操作?

Unity引擎是会自动根据依赖关系去搜寻依赖的资源的,但需要注意的是,依赖的AssetBundle文件必须存在。也就是说,依赖关系包如果后续还会使用的话,是不应该被Unload的,否则后续AssetBundle加载上来后,被依赖的资源是无法找到的。对于Unity 5.3之前的版本,出于内存的考虑,开发团队可以通过CreateFromFile或LoadFromCacheorDownload来加载AssetBundle,既可以保留AssetBundle之间的依赖关系,同时又不会产生Webstream。

开发团队可以参考你应该了解的AssetBundle管理机制,进一步了解相关API。


Q2:请问一下,我两个预设都引用了第三个AssetBundle的贴图,如果不希望这张贴图存在两份,一定要等这两个预设都加载好了,才能卸载贴图的AssetBundle吗 ?

是的,但并不是因为这样做会使“这张贴图存在两份”,而是因为如果先卸载贴图的AssetBundle会导致后续加载两个预设时会丢失依赖,即找不到贴图。如果脚本中会对这个情况进行检查并重新加载贴图的AssetBundle,那么此时才会造成“这张贴图存在两份”的问题。


Q3:Resource的场景下有两个场景Scene1.unity和Scene2.unity。我要对这些文件进行打包,生成了

Scene1.assetbundle Scene1.assetbundle.meta Scene2.assetbundle Scene2.assetbundle.meta

如果我有相同的资源,理论上它会在这两个包里各存一份,这样就造成了包体过大。所以有没有办法把共享资源做成依赖项单独打包,这样的话每个场景就不会过大了。Unity 5.x的BuildAssetBundles打包机制是否和Unity 4.x不一样?原来的打包机制已经被剔除了吗?

用Unity 4.x 的 Push/Pop 是可以抽出相同的资源,并且据我们所知该方法在Unity 5.x 中也受用。根据Unity 5.x新的打包机制,只要把相同资源的 AssetBundle Name 设置好,打包时就会自动抽出来。


Q4:如果先Destroy Prefab ,然后将Prefab中用到的AssetBundle再进行Unload,这样的顺序是否会有问题 ? 我在手机上测试时发现这样做内存中就会一直存在,不释放;如果反过来, 就可以释放。另外,我是在Destroy 的时候调用的Resources.UnloadUnusedAssets();,请问这会影响最终的结果吗?

确实可能发生这种情况,在 Resources.UnloadUnusedAssets(); 时,如果还没有进行AssetBunlde的Unload 操作,那么从AssetBunlde中加载的资源依然会因为被AssetBunlde引用而无法被卸载。 开发团队可以尝试 Destory 后做 AssetBunlde的Unload,最后进行 Resources.UnloadUnusedAssets(); 。


Q5: 我们在UWA上进行了性能测试,发现安卓上同步加载AssetBundle资源会非常耗CPU, 所以近期对资源加载方式做了比较大的调整,绝大部分的资源使用异步加载的形式。 不过这里有个疑问想咨询下: AssetBundle.LoadAsync 和 WWW加载方式都可以用来异步加载AssetBundle, 但是两者API特点也不同, 目前看WWW更耗内存一些, 请问这两种方式更建议使用哪一种 ?

AssetBundle.LoadAsync 是在获取了 AssetBundle 对象之后加载其中的资源的;而 WWW 加载是在获取 AssetBundle,两者的作用是不同的。
开发者可能是希望了解异步加载 AssetBundle 的几个 API 之间的区别,相关的接口如下:

new WWW WWW.LoadFromCacheOrDownload

这两种方式的具体区别可先参考《你应该知道的AssetBundle管理机制》中的“AssetBundle加载进阶”部分。


Q6: 现在生成AssetBundle的时候每个文件会多生成一个Manifest文件,这个文件也需要一起随着AssetBundle上传吗,在资源加载的时候具体怎么用呢?

每个文件多生成的Manifest 文件是不需要上传的,其作用就是供开发人员查看AssetBundle 中的依赖关系等信息。

但除了每个文件多生成的 Manifest 以外,根目录下还会有一个与根目录同名的AssetBundle 以及 Manifest 文件,通过运行时加载这个AssetBundle,可以得到一个 AssetBundleManifest 对象,然后就可以通过这个对象得到AssetBundle直接的依赖关系。

更多信息可以参考http://docs.unity3d.com/ScriptReference/AssetBundleManifest.html