AssetBundle基础知识

AssetBundle

assetBundle可以理解为一种压缩包,这个压缩包可以包含特定平台的资源 (模型,贴图,prefab,音频,场景等),可以在运行时进行动态的加载。
一个AssetBundle实际上有两个部分组成:

1.一部分是包含资源文件,叫做AssetBundle压缩包,
压缩包里有两种文件类型:
1.序列化文件和资源文件。序列化文件比如场景,prefab等。
2.资源文件比如贴图,模型网格,音频,视频等二进制数据。
2。另一部分是压缩包中包含资源的映射信息。通过代码加载AssetBundle时就需要从这一部分中获取资源对应的位置信息

AssetBundle 结构

一个AssetBundle包括两个部分:包头和数据段
包头:包含有关AssetBundle的信息,比如标识符,压缩类型和内容清单(manifest:manifest是一个用对象名字做key的查找表)每个条目都提供一个字节索引,该索引指示在AssetBundle的数据段中可以找到给定对象的位置。
在大多数平台,这个查找表是用平衡搜索树实现的,(除了Windows和OSX派生的平台(包括IOS平台)是用红黑树实现)因此,构建这个清单的时间消耗会随着ab内的资源数量的增加而线性增加。
数据段: 通过序列化AB内的资源的原生数据。
如果用LZMA压缩,将压缩所有序列化资产的完整字节数组;
如果是LZ4压缩,每个资源都是分开压缩的;
如果没有压缩,就都保存原生字节流。

AssetBunde压缩格式

Unity支持三种AssetBundle打包的压缩方式:
1.LZMA
是一种默认的压缩形式,这种标准的压缩格式是一个单一LZMA流序列化文件,并且在使用前需要解压整个包体。LZMA压缩是比较流行的压缩格式。能使压缩后文件到达最小,但是解压相对缓慢,导致加载时需要较长时间的解压时间。
2.LZ4
Unity支持LZ4压缩,能使的压缩量更大,而且在使用资源包前不需要解压整个包体,LZ4压缩是一种Chunk-based算法,所有从LZ4压缩包中加载时,只要这对象的对应模块被解压就可以,这样速度会更快,也就是不需要等待加载整个包体。
3.不压缩
不压缩的方式打包后包体会很大,但是下载时,访问非常快。不推荐使用

AssetBundlede的加载

1.AssetBundle.LoadFromFile 从磁盘上的文件同步加载AssetBundle 此API消耗的最大内存量将至少是AssetBundle大小的两倍
2.AssetBundle.LoadFromFileAsync 从磁盘上的文件异步加载AssetBundle
3.AssetBundle.LoadFromMomory 从内存同步创建AssetBundle (建议不要使用此API)
4.AssetBundle.LoadFromMomoryAsync 从内存异步创建AssetBundle
5.AssetBundle.LoadFromStream 从托管流同步加载AssetBundle
6.AssetBundle.LoadFromStreamAsync 从托管流中异步加载AssetBundle
7.UnityWebRequestAssetBundle.GetAssetBundle 创建UnityWebRequest,用于通过HTTP GET下载Unity资源包

Asset 加载

1.AssetBundle LoadAsset 从资源中加载指定的资源
2.AssetBundle.LoadAssetAsync 从资源中异步加载指定的资源
3.AssetBundle.LoadAllAsset 加载当前资源包中所有的资源
4.AssetBundle.LoadAllAssetAsync 异步加载当前资源包中所有的资源

Asset 卸载

1.AssetBundle.UnLoad 卸载捆绑包中的所有资产,卸载释放与包对象关联的所有内存

1.AssetBundle.UnLoad(false) 这是仅仅销毁AssetBundle对象包含的资源,任何从此包中加载的实际对象保持不变,也将无法从此AssetBundle包中加载任何其他的对象,释放的是AssetBundle的内存镜像,不包含Load创建的Asset内存对象,
2.AssetBundle.UnLoad(true)销毁AssetBundle对象包含的资源, 同时销毁从此包中加载的资源对象,会释放AssetBundle.LoadAsset等加载的资源对象。如果场景中有游戏对象引用这些资源,则他们的引用都会丢失。

对于用户来说,如果选择 AssetBundle.Unload(true),用户必须确保 Bundle 中已经加载的 资源 是没有被引用的,否则就会发生 资源丢失。
如果选择 AssetBundle.Unload(false),用户就要承担起卸载 已加载资源 的责任,如果处理不当,就可能造成 资源重复

2.Resources.UnloadAssets 仅能释放非GameObject和Component的资源,比如, Texture,Mesh等真正的资源,对于由prefab加载出来的Object 或Component, 则不能通过该函数来释放

3.Resources.UnloadUnusedAssets 释放没有引用的Asset,这个函数会扫描全部的对象,开销比较大,一般只在切场景时调用。

AB卸载策略

加载AB后,实例化 ,然后直接卸载AB
关闭 卸载AB
Image在OnDestoy的时候卸载图片AB

AssetBundle的粒度

每个AssetBundle包含多少资源

AssetBundle 打包策略

1.逻辑实体分组(Logical Entity Grouping)

捆绑用户界面屏幕的所有纹理和布局数据
捆绑一个角色/一组角色的所有模型和动画
捆绑跨多个级别共享的场景片段的纹理和模型

常用的策略
按功能出现需要的资源,将需要的资源捆绑到一个AB里,这样,加载该功能界面的时候,只要加载改AB就可以,
如果功能比较复杂,可以视情况拆分粒度,逻辑实体分组是可以下载内容DLC的理想选择,因为通过这种方式将所有的内容分开,可以更改单个实体,而无需下载其他不变的资产,开发必须精确的了解项目将在何时何地使用每种资源。

2.类型分组 (Type Grouping)

预制体
音频
脚本
类型分组是构建多个平台使用的AB较好的策略之一

并发内容分组

每个关卡都包含完全独特的角色,纹理,音乐等

基于场景的包,每个场景约束包含大部分或所有场景依赖关系
这些资产将同时加载和使用。

将经常更新的对象与很少更改的对象分离
把需要同时加载的Asset尽量打包到同一个AB里,例如模型,其纹理和动画。
如果一次经常加载少于50%的捆绑包,请考虑将其拆分
如果你发现多个AssetBundle中的多个对象都依赖于完全不同的AssetBundle中的单个资产,请将依赖关系移至单独的AssetBundle.
根据依赖树进行的最优打包策略,公共资源单独打ab,独立资源打到一起.
如果不太可能同时加载两组对象 如:标准和高清资产,请确保它们位于自己的AssetBundle中。
考虑合并较小(小于5到10个资产)但经常同时加其内容的AssetBundle
如果一组对象只是同一对象的不同版本,请考虑使用AssetBundle Variants
通常情况下,1m左右的AssetBundle包加载性能最好,沉余也可以接受,但是在5.3版本以后,对于AB文件大小其实不必在限定于1MB之内。使用LZ4压缩,基于其Chunk的加载特点,AB加载很快,且内存占用要比之前小很多,所有LZ4的AB其实可以考虑更加粗粒度一些。
shader 字体等其他细碎并且需要常驻内存的资源打包到一起,启动游戏的时候常驻内存
根据项目实际需求将需要经常热更新的资源进行单独打包。

生成AB后获得2(n+1)个文件*
1.对应资源的AssetBundleName,AssetBundleName.manifest:这是资源的集合,实际运行时需要加载的不需要对应Manifest,所以要记录manifest的信息,然后拷贝ab不拷贝manifest
2.AssetBundle 文件所在文件夹名字,AssetBundle文件所在文件夹名字.manifest:资源依赖信息
3.主bundle保存了所有的manifest(主要是各个bundle的依赖关系)

加载AB内存变化

  1. AssetBundle加载完 AssetBundele.Load ,内存多了文件镜像
  2. 实例化预制体,显存多了可视对象
  3. Texture 加载以后是到内存,显示的时候才进入显存的Texture Memory。
  4. 所有的东西基础都是Object
  5. Load 的是Asset,Instantiate的是GameObject和Object in Scene
  6. Load的是Asset要Unload才能卸载干净,new的或者Instantiate的object 可以直接Destroy

Load和Instantiate

AB加载和释放
AssetBundle.Load(同Resources.Load):从AssetBundle的内存镜像里读取并且创建一个Asset对象,分配相应内存用于存放
预制体实例化Instantiate
一个Prefab从AssetBundle里Load出来,里面可能包括:GameObject,transform,mesh,texture,material,shader,script,和各种其他Asset你实例化一个预制体,其实是一个对Asset进行克隆+引用结合的过程
其他mesh / texture / material / shader 等,这其中些是纯引用的关系的,包括:Texture和TerrainData
还有引用和复制同时存在的,包括:Mesh/material /PhysicMaterial。
引用的Asset对象不会被复制,只是一个简单的指针指向已经Load的Asset对象。这种含糊的引用加克隆的混合, 大概是搞糊涂大多数人的主要原因。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值