AssetBundle 全解析

AssetBundle概念

1 存档文件,包含可在运行时加载的特定于平台的资源(模型、纹理、预制件、音频剪辑甚至整个场景);AssetBundle 可以表达彼此之间的依赖关系;目前一般情况下采用 LZ4 压缩方式.
2 文件包含 2 种序列化文件(引用)和资源文件;
序列化文件包含分解为各个对象并写入此单个文件的资源,依赖关系,映射等;
资源文件只是为某些资源(纹理和音频)单独存储的二进制数据块,允许我们有效地在另一个线程上从磁盘加载它们.
3 打包分为随包资源,以及增量包资源(热更资源).
随包资源跟随 apk,ipa 进行安装;
将打的增量包上传到平台资源发布(CDN)服务器,游戏内进行下载;

第一步:了解复杂的Unity3D项目中的资源依赖关系

1.依赖关系
.在这里插入图片描述
2. 在U3D的Project视图中,右键选择 Select Dependencies 可以查找到此对象所依赖的资源,如果想知道,哪个资源依赖了此资源,则需要用到下面的方法 正向依赖查找:AssetDatabase.GetDependencies(“xxx”); 反向依赖查找:

private static readonly string[] SearchObjects =
{
“.prefab”,
“.unity”,
“.mat”,
“.asset”,
“.controller”,
“.anim”,
“.ttf”,
“.shadervariants”,
“.shader”,
“.spriteatlas”,
“.spriteatlasv2”,
};
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string guid = AssetDatabase.AssetPathToGUID(path);
string[] files = Directory.GetFiles(Application.dataPath, “.”, SearchOption.AllDirectories)
.Where(s => SearchObjects.Contains(Path.GetExtension(s).ToLower())).ToArray();
int length = files.Length;
for (int i = 0; i < length; i++)
{
string filePath = files[i];
bool isCancel = EditorUtility.DisplayCancelableProgressBar(“匹配资源中”, filePath, (float) i / length);
if (Regex.IsMatch(File.ReadAllText(filePath), guid))
{
Debug.Log(filePath + " 引用到 " + path);
}
}

  1. 资源之间的依赖,并不能确认AB包之间是否有依赖关系,只能等打出AB包之后,根据AssetBundleManifest来判断AB包之间的关系,
    但是如果熟悉AB包之间的打包依赖规则,就可以很明确的推断,资源打成AB包之后是否存在依赖关系了!

第二步:设置AB包的打包方式

  1. 在Assets文件夹下创建BuildAssets文件夹
    在这里插入图片描述
  2. 打包时,只搜索BuildAssets文件夹内的资源,在.

AllFileExtension = new Dictionary<string, string[]>()
{
{ “Animates”, new []{“.anim”,“.controller”} },
{ “Binarys”, new []{“.zip”} },
{ “Configs”, new []{“.asset”} },
{ “Fonts”, new []{“.ttf”,“.asset”} },
{ “Materials”, new []{“.mat”} },
{ “Prefabs”, new []{“.prefab”} },
{ “Scenes”, new []{“.unity”} },
{ “Shaders”, new []{“.shader”,“.shadervariants”} },
{ “SpriteAtlas”, new []{“.spriteatlas”,“.spriteatlasv2”} },
{ “Textures”, new []{“.png”,“.jpg”,“.jpeg”,“hdr”} },
};

  1. 然后BuildAssets文件夹内的资源依赖其他文件夹内的资源,而不是BuildAssets文件夹内的资源互相依赖,此方式必须要每天进行一次检查,也就是说,BuildAssets文件夹内的每个资源都是一个AB包.
    如果其他文件夹内的资源被依赖次数超过5次,并且 5*size 大于100KB,则将其设定为一个AB包,并通知开发人员,将其移动到BuildAssets文件夹内.
  2. 每次打包出来的 assetBundleManifest 需要代码检查,其中不能出现互相依赖的包体,如果出现互相依赖的包体,需要通报开发人员.

第三步:加载AB包

AB关系图如下:
在这里插入图片描述
内存解析如下:
在这里插入图片描述
三层内存与AB的关系都在图中表现出来了.
AB加载的方案是从磁盘加载,严禁从网络加载,这点在正规的游戏开发中都是这么做的!加载方法
//从磁盘上加载AB包

public static AssetBundle LoadFromFile(string path) //同步加载
public static AssetBundleCreateRequest LoadFromFileAsync(string path)//异步加载

  1. 在磁盘上面,AB包是一个zip包,经过了LoadFromFile方法调用之后,AssetBundle对象是镜像内存.镜像内存解压成资源,资源再被实例化成可以在Hierarchy(类似)上面使用的GameObject,也可以说是在Hierarchy(图形显示)容器内.
  2. 单纯卸载一个AB包的镜像内存需要使用 AssetBundle.Unload(false);

第四步:加载AB包的资源

AssetBundle对象,加载进内存,也就是从镜像内存解压了一份出来.
类比在电脑上解压了一份ZIP,此时ZIP与解压的东西都存在磁盘上,
同理,AB包此时在内存中存在2份一份是压缩文件,一份是解压的文件.
//从AB包的镜像压缩内存中解压出资源

public Object[] LoadAllAssets()
public T LoadAsset(string name);

卸载这个地方的内存是极其恶心的问题,很多人在这个地方肯定会踩坑,这个地方的API也机器混乱,下面如果不对,请及时联系并指出.
单纯卸载一个AB包解压的内存需要使用 Resources.UnloadAsset(Object assetToUnload);
卸载全部的目前没有使用的解压的内存需要使用 Resources.UnloadUnusedAssets();
单纯卸载一个AB包的解压的内存与镜像内存 AssetBundle.Unload(true);
卸载所有AB包目前没有在被使用的解压的内存与镜像内存 AssetBundle.UnloadAllAssetBundles(false);
卸载所有AB包的解压的内存与镜像内存 AssetBundle.UnloadAllAssetBundles(true);

第五步

实例化prefab;将解压的内存进行实例化,此实例化只有prefab需要,其他AB包里面的资源如果不属于prefab就不需要实例化,prefab本身是一个文本文件,里面全是引用. 可以将prefab当成一个类模板,而其他资源类型的AB包,则可以被直接使用.

UnityEngine.Object.Instantiate(template);

此时的卸载与上面的AB没有关系了UnityEngine.Object.Destroy(xxx);即可

内存分析
三份内存:从磁盘中加载到内存中的压缩文件 ,
解压缩出来的资源文件.
在Hierarchy中创建的对象.

两份内存:从磁盘中加载到内存中的压缩文件 ,
解压缩出来的资源文件

个人总结的打包策略

1 直接将数据打包到 Assets/StreamingAssets/ 文件夹下面

BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, “GameStart”,EditorUserBuildSettings.activeBuildTarget, BuildOptions.CompressWithLz4HC);

2 自定义打包策略(一律纯小写,无数字)

  1. 建立一个ScriptObject,设置不同类型的文件路径,分为:prefab,fbx,scene,shader,sound,json,xml等
  2. 根据依赖关系生成不冗余的 ab 包 (AssetDatabase.GetDependencies)
  3. 生成自己的依赖关系表
  4. 根据自己的依赖关系表加载 ab 包
  5. 多个资源可设置同一个 ab 的名字;多个资源可打包成一个 ab 包,ab的资源名字也是文件名字,后缀名一般跟.ab或.unity3d

ab 名字是adc
ab 包,打成的文件名是abc.ab
ab 包中的资源有图片,音频,mesh,prefab,脚本等

3 打包

AB包的分组方式

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

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

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值