0x00
一下子看了太多,还是比较细地看的,因为是英文的文档如果不仔细读,感觉太容易左进右出了……现在来整理下能记住的,后面实际使用的时候再来完善。
现在 unity 在推新功能,可定位资源管理系统( The Addresssable Asset System ),可以根据 Address 进行加载(本地或者服务器的)特定资源,并无缝连接多种资源管理模式。
Resources.Load 和 AssetBundle( AB 包 )
Resources 方法加载资源需要在 Asset/Resources 目录下,放置资源,加载时根据文件夹内部的路径进行加载。
本想在官方文档看看关于这两者的具体区别,没想到误打误撞找到了 Unity Learn,但是看样子只有英文的教程,我先看看吼。
这一篇是 Assets, Resources and AssetBundles
加载资源的几种方式:
- 直接引用
- Resources 目录加载
- AssetBundle 资源管理
0x01
直接引用说的就是,在脚本中定义一个显示在 Inspector 中的对象,将所需要的资源挂载上去的方法。
0x02
Resources 目录是 Unity 提供的一个特殊文件夹,用来管理资源,Resources 目录中的资源(文件,prefabs,图像,音频等等)可以在脚本中根据实际存放的目录结构( path )使用 Resources.Load(“path”) 来动态加载资源文件。
但是使用 Resources 目录管理资源有很大的问题,官方直接给出的使用建议就是:别用。(实际上随着推出 Addressable Asset System 现在已经都被标记过时的了)在大型项目中使用会造成包体过大,构建的应用启动时间过长,内存管理也更困难。对于移动平台或需要热更新的场景下极不友好(无法进行增量更新 incremental content upgrades ),同时这种依赖资源名的调用方式很容易在替换资源时出现问题。
原因是,Resources 目录下的全部资源文件都会在构建可执行文件时进行打包,而且是工程中的所有 Resources 文件夹都会合并成一个序列化的文件,这类似于将所有的资源打包成了一个 AssetBundle,同样包含索引信息(index)和资源数据(metadata)。而且,并不是所有的 Resources 资源都要在第一个场景中使用。
但是这种方式贵在使用方便,而且在特定条件下也是有使用价值的,比如包含的资源文件体积很小,基本不会改动或是与平台设备等无关的内容。(比如:全局使用的单例 MonoBehaviour prefab,第三方组件的配置文件。)
其实总结起来,不要用 Resources 的方法,但是项目足够小,可以用……快速的原型搭建都可以用,只是到了全面开发阶段,用 AssetBuddle 更好,提供了更多的灵活性。
0x03
反过来说 AssetBundle 就像是“被拆分开了的 Resouces 目录”。AssetBundle 由头文件( Header )和数据段( Data Segment )组成,数据段中包含着所有资源对象,而头文件中包含了 AssetBundle 的信息,此 AB 包的标识符( Identifier ),压缩类型( Compression Type,是否压缩,LZMA - 全包压缩,LZ4 - 单独压缩)以及数据清单( Manifest,对象名作为 key 用来查找数据段位置)。
对于使用 AssetBundle 的工程,工作流程则成了先将资源按照一定的方式打包成多个 AssetBundle( BuildPipline.BuildAssetBundles 方法 ),然后将这些二进制文件放到 StreamingAssets 目录下( 类似 Resources,但构建时不会进行打包的处理 ),在运行时加载需要的 AssetBundle( 4 个 API,最快最好的是 AsseBundle.LoadFromFile ),之后使用 AssetBundle 中的资源对象( 3 种 6个 API,LoadAllAssets 最快,LoadAsset,LoadAssetsWithSubAssets )。
对于 AssetBundle 的卸载需要有一定的讲究,因为两种卸载方式各有各的好处(坑?),卸载 AssetBundle 使用 API AssetBundle.Unload(bool),参数表示是否卸载从此 AB 包中加载的资源对象实例。true 时,会立即卸载实例化的所有对象,造成的问题是如果场景中依然有对象对这些卸载了的资源的对象进行访问会出现 missing 的情况(确保不会再使用,比如场景切换时);false 时,会在下次加载同样的 AB 包时,造成同样的资源对象重复的情况,因为先前加载的对象没有被卸载,并与 AB 包切断了联系,在重复加载时并不会修复这种联系,所以内存中有了重复的对象(对这些资源对象进行清理,如引用计数)。
而为了便于开发,常会加入一个“模拟模式”,在编辑器下启动时,在模拟模式下,会将对 AssetBundle 的资源请求重定向到 Assets 目录中,直接调用源资源,节约了打包的时间,可以参考 AssetBundle Manager。