Unity 3D-旧版AssetBundle(API介绍&实战)

一、相关API的介绍

1.BuildPipeline.BuildAssetBundle :打包常规资源生成AssetBundle.

Unity 3D-旧版AssetBundle(API介绍&实战)

  • Object mainAsset:指定mainAsset,这样解析该AssetBundle包的时候可以通过assetBundle.mainAsset得到。
  • Object[] assets:指定所有asset,传入对象数组.解析的时候可以通过LoadAsset("name")得到。
  • pathName:指定生成的AB包的存储路径
  • BuildAssetBundleOptions:打包时候的一些特定属性选项。
  • 一些选项如下表所示
属性 说明
CompleteAssets 用于保证资源的完备性,默认开启
CollectDependencies 用于收集资源的依赖项,默认开启
DeterministicAssetBundle 用于为资源维护固定ID,默认开启
ForceRebuildAssetBundle 用于强制重打所有AssetBundle文件,新增
IgnoreTypeTreeChanges 用于判断AssetBundle更新时,是否忽略TypeTree的变化,新增
AppendHashToAssetBundleName 用于将Hash值添加在AssetBundle文件名之后,开启这个选项可以直接通过文件名来判断哪些Bundle的内容进行了更新(4.x下普遍需要通过比较二进制等方法来判断,但在某些情况下即使内容不变重新打包,Bundle的二进制也会变化),新增
ChunkBasedCompression 用于使用LZ4格式进行压缩,5.3新增
UncompressedAssetBundle 打包时不进行压缩,默认关闭
  • targetPlatform:适用平台。选择该AssetBundle应该使用哪些平台
属性 说明
StandaloneWindows 打包32位windows平台上的包
StandaloneWindows64 打包64位windows平台上的包
IOS 打包ios平台上的包
Android 打包Android平台上的包

2.BuildStreamedSceneAssetBundle:将场景打包成AsssetBundle包

Unity 3D-旧版AssetBundle(API介绍&实战)

  • levels:欲打包的所有场景文件路径。
  • localtionPath : 生成AssetBundle包保存的相对路径。
  • target : 同上。
  • options : 同上。

注:WWW下载好场景AssetLevle包之后通过获取成员属性assetBundle就可以吧场景信息读入到内存中了。然后只需要通过Application.LoadLevel(name)就可以加载对应的场景。

3.WWW类,通过一个路径进行下载(服务器和本地的操作都一样)

WWW www = new WWW (Url);

  • Url:下载路径,本地下载请加上 file://,服务器下载请加上 http://

注:www下载后的得到的对象可以通过获取成员属性assetBundle,即可得到下载文件的AssetBundle包。不过该方法下载得到的资源统统是放在内存里面的,也就是说每次打开游戏都需要重新下载。

4.WWW.LoadFromCacheOrDownload : 通过路径和版本号下载

public static WWW LoadFromCacheOrDownload(string url, int version, uint crc = 0);

  • Url:下载路径,本地下载请加上 file://,服务器下载请加上 http://
  • Version:版本号;这个版本号不需要你自己去维护,每次Unity从服务器下载资源的到本地的时候都会维护这个资源的版本号。当下次调用该API下载该资源会先对比本地版本号和参数版本号是否匹配,如果不匹配就从服务器重新下载,否则就从磁盘缓存文件中读取。

注: www下载后的得到的对象可以通过获取成员属性assetBundle,即可得到下载文件的AssetBundle包。该方法下载的资源是缓存到电脑缓存文件中的,另外按照宣雨松大大的说法,这个方法是一个异步方法,还占用内存,建议改用AssetBundle.CreatFromFile 它是一个同步方法,并且现在IOS 和 android 都支持了,最重要的一点就是用这个方法下载下载路径不需要加( file://或者 http://前缀),切记,这是一个巨坑

5.资源入栈&资源出栈

BuildPipeline.PushAssetDependencies: 资源入栈& BuildPipeline.PopAssetDependencies: 资源出栈

这个就主要用于打包的资源具有依赖关系时的场景

Push和Pop都是成对使用,一个Push/Pop对就相当于一个Layer(层),层可以嵌套,内层可以依赖外层的资源。也就是说内层某资源在打包时,如果其引用的某个资源已经在外层加载了,那么内层的这个资源包就会包含该资源的引用而不是资源本身(大大缩减了资源包的大小)。Push/Pop实际上维持了一个依赖的堆栈。那么,在加载依赖资源包时,需要注意的是:先加载依赖的资源,然后加载其他资源,需要确保这个顺序。

二:代码实战

1.单个资源文件分别打包、合并打包

  • 首先创建两个Cube并制作成perfab,删掉场景中的刚刚创建的Cube Unity 3D-旧版AssetBundle(API介绍&实战)
  • 创建脚本AssetBundleBuilt.cs编写代码如下

注意:StreamingAssets目录必须存在否则会报错,不要问我是怎么知道的

保存后回到Unity,在工具栏就挂在了我们写好的打包函数,选择做好的两个Cube的prefab分别打包,不出意外在StreamingAsset目录下就生成了我们打包的perfab

  • 创建脚本AssetBundleLoad.cs来加载我们刚刚打包好的assetbundle场景中

如下图所示,点击下图中的button 按钮,两种打包方法都可以吧资源正确的加载到场景中来 Unity 3D-旧版AssetBundle(API介绍&实战)

2.包含依赖关系的资源打包

  • 依赖关系概念的说明

回到上面的问题,打包结果如下图所示 Unity 3D-旧版AssetBundle(API介绍&实战)

显而易见两个物体一起打包的大小,和单个物体单独打包的大小一样,为什么?

答:前面说了开启BuildAssetBundleOptions.CollectDependencies时,会收集资源的依赖关系,CubeA和CubeB都是Cube用的都是同一套基础资源,只打包了一套基础资源。

扩展:如果没有使用BuildPipeline.PopAssetDependencies()来进行依赖打包,那么 打包物体 会把其引用的资源都打包到自己的assetbundle 中。如果引用的资源是图片、sprite或自定义的shader(内置的shader不会打包,这里的自定义shader被unity看作是一种资源,打包处理的时候也是如同资源来处理的),那么会打包到assetbundle 中。但如果引用的是代码,那么会打包一个对工程中代码的引用,也就是说引用的代码必须存在于工程中,这样当资源被加载到本地的时候才可以和本地的代码进行关联,如果本地没有这个代码,则会丢失对这个脚本的引用。

那么问题又来了,开启了BuildAssetBundleOptions.CollectDependencies一起打包,就会只打包一套公用的基础资源,直接把所有资源一起打包不就OK了?

答:答案显然是否定的,很明显AssetBundle就是实现资源的动态加载,方便更新,这样做的话,一但某个包含的资源更改,就需要重新打包,替换整个AssetBundle资源包这个肯定是不合理的。

因此问题的关系就在与,分析资源之间的依赖关系,人为的分级打包,这样既避免了一起打包的尴尬,又不至于重复打包的坑爹。

这就是下面要说的具有依赖关系的资源的打包流程

  • 依赖打包的策略

依赖关系打包的实质就是将那些被依赖的资源先打包 ( 这里我把这类资源用"底层资源"代替 )。对于那些引用了底层资源的资源 ( 这里我把这类资源用"顶层资源"代替 )在打包的时候就不用再将底层资源打包到自己的包里面,而是添加对底层资源的引用,这样就避免了重复打包底层资源了。而且不同资源可以根据项目的分类分别打包到不同的AssetBundle包里面,也方便了后期的更新和维护。

  • 依赖打包案例分析

还是用上面的例子,我给上面的两个Cube添加同一个蓝色的材质球blueMaterial,那么他们的依赖关系就是 CubeA-->blueMaterial,CubeB-->blueMaterial,那么他们的打包顺序就可以按照下列方式进行 blueMaterial-->CubeA-->CubeB,CubeA与CubeB是同一级所以可以任意交换CubeA,CubeB的顺序,当然也可以CubeA,CubeB一同打包,这个也取决于实际的应用场景

  • 按照依赖关系分级打包

借助以下两个函数实现 BuildPipeline.PushAssetDependencies: 资源入栈,BuildPipeline.PopAssetDependencies: 资源出栈。

这里提供一个使用技巧:

1.先把所有材料编号:A-blueMaterial,B-CubeA,C-CubeB。 2.然后将每个编号两边加上括号,表示每个材料都在一个独立的栈:(A),(B),(C) 3.如果X依赖Y,那么X的栈加入Y的栈里:(A(B)),(A(C))。 4.然后合并:(A(B)(C)),就可以得到最终的关系栈

按照这个策略,创建脚本RelyAssetBundleBuilt.cs打包

这样就在上面创建的工具栏上又多了一个 Create RelyAssetBundleMain选项,直接点击即可完成打包。

  • 加载依赖打包的模型

修改脚本AssetBundleLoad如下

运行场景,按钮如下 Unity 3D-旧版AssetBundle(API介绍&实战)

当我们,在加载材质之前直接加载CubeA或者CubeB,会发先如下图所示的情况,出现了材质丢失,如果先加载材质,在加载CubeA,CubeB就不会出先任何问题,所以在分析了依赖关系打包后,加载资源是先要先加载底层资源,然后一级一级往上,否者就会出错。 Unity 3D-旧版AssetBundle(API介绍&实战)

Unity 3D-旧版AssetBundle(API介绍&实战)

结语

以上就是我对于AssetBundle旧版系统的一些学习应用,有什么问题可以留言交流,后续博客会讲到AssetBundle的新版系统的用法,欢迎围观~~~

最后来一发实验Demo的下载地址(毕竟 4.x时代的,就不放Github了)

繁夜

发表评论


:[微笑]::[撇嘴]::[色]::[发呆]::[得意]::[流泪]::[害羞]::[闭嘴]::[睡]::[大哭]::[尴尬]::[发怒]::[调皮]::[呲牙]::[惊讶]::[难过]::[酷]::[冷汗]::[抓狂]::[吐]::[偷笑]::[可爱]::[白眼]::[傲慢]::[饥饿]::[困]::[惊恐]::[流汗]::[憨笑]::[大兵]::[奋斗]::[咒骂]::[疑问]::[嘘...]::[晕]::[折磨]::[衰]::[骷髅]::[敲打]::[再见]::[擦汗]::[抠鼻]::[鼓掌]::[糗大了]::[坏笑]::[左哼哼]::[右哼哼]::[哈欠]::[鄙视]::[委屈]::[快哭了]::[阴险]::[亲亲]::[吓]::[可怜]::[笑哭]::[doge]::[泪奔]::[无奈]::[托腮]::[斜眼笑]::[喷血]::[惊喜]::[骚扰]::[小纠结]::[我最美]::[羊驼]::[幽灵]::[吃]::[OK]::[爱你]::[抱拳]::[勾引]::[强]::[弱]::[拳头]::[爱心]::[喝彩]::[西瓜]::[啤酒]::[玫瑰]::[凋谢]::[礼物]::[拥抱]::[月亮]::[菊花]::[棒棒糖]::[蛋]::[刀]::[菜刀]::[炸弹]::[手枪]:

刷新评论