当前位置:   article > 正文

包打包和解析过程 unity_Unity AssetBundle 解析 (一)AB包介绍与构建

ab包的纹理和场景的纹理

8ab6c3741fddcfc4f07f00b7cd1c935e.png

Unity AssetBundle 解析 (一)AB包介绍与构建

介绍

AssetBundle是Unity提供的一种资源存储压缩包,包含了一些Unity的资源,如图片,模型,纹理,音视频等等,也可以包含用户自定义的二进制文件。提供了一种程序运行时动态加载资源包的方法,如游戏中不同版本的资源更新即通过更新资源AB包即可。

Unity官方文档描述AssetBundle为一个容器,就像文件夹一样,包含其他文件。这些其他文件有两种类型,一种是序列化文件,包含资产分解成单独的对象并写到该单个文件中。(o((⊙﹏⊙))o,在说什么);另一种是资源文件,是为某些资产(纹理和音频)单独存储的二进制数据块,以允许Unity从另一个线程上的磁盘有效加载它们。

总而言之,AssetBundle就是一种资源包,让你能在运行时动态的加载卸载它,也可以灵活更新,即可以无需放在游戏本地,大大降低了包体大小。

NOTE
Unity提供了两种加载资源的方法(2018.2之后又新增一种)
  1. 通过放在本地特殊文件夹Resources下直接加载资源,通过Resource.Load()这个API加载就行,简单粗暴,非常适合新手,可以不用管资源怎么管理,加载就完事了。但有缺点,不利于拓展,也无法分平台发包以及从线上下载等。
  2. 本文要介绍的AB包方式,应该是目前比较通用的方案
  3. 2018.2版本后新增的可寻址方案Addressable,这个后续再写个博客

其实无论是用Resources或者Addressable加载方式,底层都是基于AssetBundle实现的,只是Unity引擎会自动做这步操作

官方文档:

https://docs.unity3d.com/Manual/AssetBundlesIntro.html​docs.unity3d.com

1. 工作流

  1. 设置资源的BundleName以及BundleVariant
  2. 打包AssetBundle
  3. (将AB包上传到服务端,若放在本地则可跳过)
  4. 加载AssetBundle
  5. 实例化AssetBundle中的资源
  6. AssetBundle的卸载

2. 打包AB包

设置资源的AssetBundleName和Variant

AssetBundleName与Variant介绍

将要打包成AssetBundle的资源设置AB包名字和变体名字

  • AssetBundleName: 即是该资源要打包进哪个AB包里面,若多个资源的AssetBundleName相同(且变体名Variant也相同)则这些资源会被打包到同一个AB包里,换言之,这个AB包包含了多个资源。
AssetBundleName不能包含"."这个特殊字符,会与variant产生冲突
使用/分隔符可以按层级建AB包,如AssetBundleName为A/B/C的AB包会被打包成A文件夹下的B文件夹下的名字为C的AB包
  • Variant: 类似后缀名的东西,称为变体,默认为.assetbundle,一般后缀大家都设置为.assetbunlde和.unity3d,那有人会用,这个有啥用。主要的用途应该用来做版本控制,即同种资源的不同形态下的加载,如不同语言包的同类型资源的加载,如可命名资源a的不同变体为http://a.cn,a.en等,根据不同的语言包加载不同的AB包。
参考链接: https:// dev.twsiyuan.com/2017/0 5/unity-assetbundles-variants.html

AB包的分组方式

将哪些资源打包到一个AB包下是让人头疼的事情,就像你要把你的衣服放进衣柜里,总而言之就是整理的过程,而这种事情越早确定越好,到后期再更改就显得很麻烦。

Unity官方推荐的分类方式有以下几种:混合搭配才是王道

  • 按逻辑进行分类
    即按该资源被哪个功能应用到,同种功能用到的资源打到一个AB包内
    • 如将一个UI界面的所有图片纹理,布局文件打包到一个AB包
    • 将一个角色的所有动画,模型打包到一个AB包
    • 将一些公用的资源打包到一个AB包
  • 按类型分类
    将同一个类型下的资源打包到一个AB包中
    • 如将Windows和Mac平台下使用到的不同Shader资源分类打包
    • 将不同版本的Unity AB包进行分类打包
  • 同时使用的打包
    即考虑到哪些AB包可能会在某个时间段一起使用,则打包到同一个AB包中
    • 如某关卡下需要加载的所有资源一起打包
    • 某个场景下需要加载的所有资源,你应该尽可能将所有AB包依赖项都打包进来,避免加载其他依赖项

以下是官方给出的一些分类建议:

  • 将经常更新和很少更改的资源分开打包
  • 将基本会同时使用的资源打包,如模型和它用到的纹理,动画一起打包
  • 将一些很多资源会引用到的公共资源分开打包,避免重复打包
  • 如果两组几乎不可能同时加载的资源分开打,如Standard和High解析度资源分开打
  • 如果一次加载某个AB包经常用到少于50%其中的资源,则应该分开打包
  • 考虑合并比较小但经常一起使用的AB包
  • 如果某组资源只是同个资源的不同版本分类,使用variant打包(如不同语言版本的同个资源)

设置的方式

无非两种方案,一种手动,一种写脚本按一定规则变成自动

  • 手动方案,在资源的Inspector栏目手动添加/设置AssetBundleName和Variant

c82f4b571ec79b3bcde6463c64317d7f.png

一键自动设置AssetBundleName和Variant
可设置规则,如按文件夹进行AB包的命名,同个文件夹下的资源打包到同一个AB包
设置AB包AssetBundleName和Variant的API如下:

AssetImporter.GetAtPath(filePath).SetAssetBundleNameAndVariant(bundleName, bundleVariant);

Build AssetBundle

前期准备做好了之后,这里就比较简单了,调用Unity的打包API就OK了,不过这里需要注意打AB包的一些参数设置,不同平台,不同的压缩方式等。

  1. //方式1. Unity会遍历所有设置过AssetBundleName及Variant的文件进行全局打包
  2. BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
  3. BuildAssetBundleOptions.None, BuildTarget.StandaloneOSX);
  4. //方式2. 通过一个BuildMap打包指定的文件
  5. AssetBundleBuild[] buildMap = new AssetBundleBuild[2];
  6. buildMap[0].assetBundleName = "enemybundle";
  7. string[] enemyAssets = new string[2];
  8. enemyAssets[0] = "Assets/Textures/char_enemy_alienShip.jpg";
  9. enemyAssets[1] = "Assets/Textures/char_enemy_alienShip-damaged.jpg";
  10. buildMap[0].assetNames = enemyAssets;
  11. buildMap[1].assetBundleName = "herobundle";
  12. string[] heroAssets = new string[1];
  13. heroAssets[0] = "char_hero_beanMan";
  14. buildMap[1].assetNames = heroAssets;
  15. BuildPipeline.BuildAssetBundles("Assets/ABs", buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);

压缩方式

  • BuildAssetBundleOptions.None
    使用LZMA格式压缩,这是序列化数据文件的单个压缩LZMA流(官方翻译的),LZMA压缩要求在使用整个AB包之前先对其进行解压缩。所以这种压缩方式的AB包体最小,但同时加载时间最长(永远的定律)。在第一次加载解压完成后,Unity会对他进行重新压缩为LZ4的格式,这种格式无需解压整个AB包即可读取里面的资源。这种方式一般使用在当加载某个AB包时就会使用到其里面所有的资源。如某个角色的AB包,里面的模型,动画,纹理等都会被同时需要,这种方案就比较适合。
通过UnityWebRequestAssetBundle加载的LZMA格式AB包将自动重新压缩为LZ4压缩,并缓存在本地文件系统上。而通过自己写的下载方案,则可以调用AssetBundle.RecompressAssetBundleAsync API重新压缩
  • BuildAssetBundleOptions.UncompressedAssetBundle
    这种方式的AB包完全没有压缩,所以包体是最大的,但同时加载的时候就比较快
  • BuildAssetBundleOptions.ChunkBasedCompression
    使用LZ4格式压缩,这种方式的包体比LZMA格式大,但无需解压完整个AB包就能读取里面的数据(LAMA就需要),LZ4使用基于块的算法,该算法允许AssetBundle分段或“块”加载。解压某些块就能使这些块中包含的资源先被读取,即使其他块的资源还未被解压。
NOTE
使用 ChunkBasedCompression具有与 BuildAssetBundleOptions.UncompressedAssetBundle差不多的加载时间,却具有减小磁盘大小的额外好处。

BuildTarget

打包平台,即要打包哪个平台的AB包,如Android平台则使用BuildTarget.Android,不同平台使用的AB包不同,无法跨平台使用。

输出文件夹

一般本地的AB包放在Unity特殊目录StreamingAssets下,通过Application.streamingassetpath读取

和Resources特殊目录一样,Unity会将该目录下的所有文件都打包,故需要特别注意,在打包不同平台的应用程序时,避免将其他平台的AB包一起打包,否则将大大增加包体大小。如Android的apk包就不应该确保StreamingAssets目录下只有Android平台的资源,其他平台的资源都是没用的,只会增加包体大小。

3. 生成的AB包文件

无论用何种方式打包AB包,最终生成的文件结构都是相同的。在同一输出文件夹下,生成的文件数目为该文件夹下 AB包数目*2+2,即假设有2个AB包打包输出到同一文件夹下,则在该文件夹下会生成6个文件。

4144f22fe9b4432a15342868c62bfd7b.png

每个AB包都会生成一份AB包本体文件(如上图的cube.a,若没有设置AB包Variant,则默认AB包后缀为.assetbundle),一份AB包的清单文件(上图的cube.a.manifest);

另外文件夹下会生成文件夹同名的两个文件,上图的StreamingAssets及StreamingAssets.manifest。StreamingAssets文件没有意义,StreamingAssets.manifest记录了一份该文件夹下AB包清单。

AB包的manifest则记录了AB包的一些依赖关系以及包含的资源清单,该清单仅用于查看,没有其他意义。

故构建AB包后真正有用的文件就是生成的AB包本体。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/82166
推荐阅读
相关标签
  

闽ICP备14008679号