技术分享连载(九)

技术分享连载(九)

最近UWA群中讨论资源打包的问题比较集中,今天我们就整理了几个与AssetBunlde打包相关的常见问题。另外,侑虎君提醒大家,优化的过程中要随时在www.uwa4d.com上进行资源检测哦。UWA助你一步步吃透项目中的每个资源!

同时如果你也是个热爱分享、愿与大家抱团进步的程序员,欢迎加入UWA的QQ群(793972859),与我们奇文分享,疑义相析。


Q1: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 设置好,打包时就会自动抽出来。


Q2: 我们在使用Unity 4.3.4开发项目的过程中会遇到锁屏后主线程卡死的问题,因此我们考虑将Unity版本降至4.1.2,但是因为之前用Unity 4.3.4版本打包的资源比较多,所以想咨询下有没有方法可以用Unity 4.1.2 加载 Unity 4.3.4 打包出的AssetBundle?

Unity 4.x 系列中各个版本 AssetBundle 是不兼容的,高版本加载低版本也有可能出现问题,所以一旦版本改动(特别是跨了大版本的改动,如 Unity 4.3 到 Unity 4.5 或者Unity 4.5 到 Unity 4.6 等等)都是需要重新打包 AssetBundle 的。


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

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


Q4: 我们将Shader放到了Resource的目录下,也已加到Editor的GraphicSetting里,也试过在加载一个空的Prefab时绑定对应的Shader。 但该Shader在Editor里无法正常显示,看运行时指向是有的,重新指一下就能显示了, 然而打包以后在手机上显示正常。

这确实是Unity已知的一个问题,Android 和 iOS 的部分Shader在打包后,在Editor 下无法正常显示。 主要原因是在打包时,只会把对应平台的Shader预编译代码(如 gles )打入包中,因此在 Editor 下会执行失败(通常 Editor 是 d3d 驱动)。 因此,目前只能尝试在Editor下重新指定Shader来绕过这个问题。


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