AssetBundle文件结构浅析
压缩方式:
AssetBundle压缩后大致文件组成:
LZMA:
压缩数据的头有13个字节,前5个字节是lzma解压缩的API需要插入的props,
接下来的4字节是解压缩后的数据库长度。使用时需要整体解包,优点是打包后体积小,
缺点是解包时间长,导致加载时间长。
LZ4格式:
相较LZMA会生成更大的压缩文件,但优点是使用时不需要整体解压。
LZ4是一种基于chunk的算法,加载对象时只有相应的chunk会被解压。
该格式需要Unity5.3以上的版本,以前的版本并不支持。
不同压缩方式使用加载API对比:
API |
未压缩 |
LZ4(块压缩) Unity5.3后 |
LZMA(流压缩) 默认压缩方式 |
WWW* |
内存:未压缩 无需额外的处理 |
内存:LZ4HC压缩 无需额外处理 |
内存:LZ4压缩 LZMA解压+下载过程中LZ4压缩 |
LoadFromCacheOrDownload |
内存:无需额外内存 需要从硬盘读取 |
内存:无需额外内存 需要从硬盘读取 |
内存:无需额外内存 需要从硬盘读取 |
LoadFromMemory(Async) |
内存:未压缩 无需额外的处理 |
内存:LZ4HC压缩 无需额外处理 |
内存:LZ4压缩 LZMA解压+LZ4压缩 |
LoadFromFile(Async) |
内存:未压缩 无需额外的处理 |
内存:无需额外内存 需要从硬盘读取 |
内存:LZ4压缩 LZMA解压+LZ4压缩+从硬盘读取 |
WebRequest (同时支持Caching) |
内存:未压缩 一般无需额外处理, 读Cache需读取硬盘 |
内存:LZ4HC压缩 一般无需额外处理, 读Cache需读取硬盘 |
内存:LZ4压缩 LZMA解压+下载过程LZ4压缩,读Cache需读取硬盘 |
AssetBundle文件结构:
通常情况下AssetBundle文件组成:
场景打包AssetBundle组成结构
AssetBundle由两部分组成:头部(header)数据部分(data segment)
- 头部保存了版本号、数据类型、文件信息、是否压缩等这些描述信息。
文件信息记录了数据部分里面的所有单个资源的文件名以及在整个AssetBundle中
文件offset和size,通过这个信息可以直接获取到AssetBundle中的某一个文件的数据。
从Unity5.3版本开始这部分数据会单独生成一个AssetBundle同名的.manifest文件。
- 数据块保存了在build AssetBundle时候标记的textures、prefabs、materials等资源文件
文件头结构(未压缩):文件字节流以'\0'结尾,且为大端方式储存。
1 // AssetBundle文件头结构 2 struct AssetBundleFileHead { 3 struct LevelInfo { 4 unsigned int PackSize; 5 unsigned int UncompressedSize; 6 }; 7 8 string FileID; 9 unsigned int Version; // bundle格式版本 3.5~4.x : Version == 3 10 string MainVersion; // 11 string BuildVersion; 12 size_t MinimumStreamedBytes; 13 size_t HeaderSize; 14 size_t NumberOfLevelsToDownloadBeforeStreaming; 15 size_t LevelCount; 16 LevelInfo LevelList[]; 17 size_t CompleteFileSize; 18 size_t FileInfoHeaderSize; 19 bool Compressed; 20 };
一个 AssetBundle是由多个asset 文件打包而成,顺序打包了这些 asset 。
序列化成这样的结构:
1 // asset 文件头结构 2 struct AssetFileHeader { 3 struct AssetFileInfo { 4 string name; 5 size_t offset; //除去 HeaderSize 后的偏移量 6 size_t length; 7 }; 8 size_t FileCount; 9 AssetFileInfo File[]; 10 };
分解出被打包在一起的多个 Asset 了,offset 表示的是除去 HeaderSize 后的偏移量。
可以用 HeaderSize 加上那个部分的 offset 得到这个部分相对于整个 bundle 的文件偏移。
对于每个 asset ,又有它自己的数据头。数据头除了基本的数据头结构 AssetHeader 外,
还有额外的三个部分:
1 // asset数据头 2 struct AssetHeader { 3 size_t TypeTreeSize; // TypeTree对AssetBundle是可选的 4 size_t FileSize; 5 unsigned int Format; // 根据Unity版本决定 6 size_t dataOffset; 7 size_t Unknown; 8 };
在发布到移动设备上时,TypeTree 是不打包到 asset bundle 中的。
每个 asset 对象,都有一个 Class ID ,可以在 TypeTree 中查到如何反序列化。
Class ID的和具体类型的对应关系,在 Unity3d 的官方文档 可以查到。
接下来是每个 AssetObject 的描述数据。
1 // Object 数据头 2 struct ObjectHeader { 3 struct ObjectInfo { 4 // int为"小端编码"的4字节整数 5 int offset; 6 int length; 7 int pathID; 8 byte classID[8]; 9 }; 10 int ObjectCount; 11 ObjectInfo Object[]; 12 };
如果想取得正确的相对整个文件的位置:
应该是文件的 HeaderSize + asset.offset + asset.dataOffset + object.Offset 。
接在 ObjectHeader 后的是 AssetRef 表,记录了 Asset 的引用关系。
用于指明这个 bundle 内 asset 对外部 asset 的引用情况。
AssetRefTable 结构如下:
1 struct AssetTable { 2 struct AssetRef { 3 byte GUID[16]; 4 int type; 5 string filePath; 6 string assetPath; 7 }; 8 int Count; 9 byte Unknown; 10 vector Refs; 11 };
每次同样的asset,打包后的包大小都不一致是因为生成AssetBundle的时候用了lzma压缩,
只要压缩前的数据有一点点不一样,那lzma 后的结果就几乎完全不一样。
想要得到一模一样的AssetBundle包,要在BuildAssetBundle的assetBundleOption
里|BuildAssetBundleOptions.DeterministicAssetBundle来确保文件的唯一性。
Manifest文件:
Manifest文件仅用于检查增量构建,运行时不需要。因此不需要打包进正式发行的游戏中。
每个AssetBundle都有一个manifest文件,包含如下信息:
- CRC(循环冗余码):资源文件的哈希码,在该AssetBundle中的所有资源有一个单一的哈希码,用于检查增量的构建。
- Type tree哈希码:在该AssetBundle中所有类型有一个单一的哈希码,用于检查增量的构建。
- Class types:该AssetBundle中所有的类类型。当为type tree做增量构建检查时将产生一个新的哈希码。
- Asset names:该AssetBundle中所有明确包含的资源名字,依赖于该AssetBundle的其他AssetBundle。
不同格式文件的打包类型:
文件格式 |
支持后缀名 |
打包后的类型 |
文本 |
txt xml |
TextAsset保存在TextAsset的text属性中 |
二进制 |
bytes |
数据保存在TextAsset的bytes属性中 |
Prefab |
prefab |
GameObject 需instantiate实例化才可以使用 |
FBX |
fbx |
添加了Animator为 GameObject,需Instantiate实例化 |
Mecanim |
N/A |
GameObject Mecanim中必须制作为预制件进行加载 |
Legacy动画 |
N/A |
同上 |
图片 |
bmp jpg png |
Texture2D Sprite |
音乐 |
aiff mp3 ogg |
Audio Clip |
ScriptableObject |
asset |
Scriptable Object派生类 |
Unity Studio输出格式:
Unity Studio和Disunity解包工具基本都是首先处理AssetBundle包,读入stream中decode。
首先检测签名,查看AssetBundle打包的平台,根据不同平台来选择不同的加载方式。
然后根据偏移和数据ID来解析stream,并将数据转为相关的文件格式。
资源类型 |
输出格式 |
图片 |
pvr 和dds |
音频 |
mp3 |
网格 |
txt |
Shader |
shader |
配置表 |
txt |
参考:
- ClassIDReference
- Unity3D asset bundle 格式简析
- Unity AssetBundle差异更新
- Unity Studio解包工具
- DisUnity解包工具
- Unity AssetBundle压缩
转载于:https://www.cnblogs.com/pinkfloyd/p/6489979.html
AssetBundle文件结构浅析相关推荐
- .net core 项目文件结构浅析
1:launch.json (配置调试用的) 通过vs code创建的项目,都会有这个文件,是启动调试的配置文件: (vscode默认支持nodejs调试) 要调试调试c#代码 需要安装 C# 插件 ...
- Electron程序逆向(asar归档解包)
要学习Electron逆向,首先要有一个Electron开发的程序的发布的包,这里就以其官方的electron-quick-start作为例子来进行一下逆向的过程. GitHub - electron ...
- MP3歌词文件格式-Lrc格式
LRC文件结构浅析 LRC概述 LRC 歌词是一种包含着"[*:*]"形式的"标签(tag)"的.基于纯文本的歌词专用格式.最早由郭祥祥先生(Djohan)提出 ...
- 浅析BMP位图文件结构(含Demo)[转]
<!--done--> 关于BMP位图格式在网上可以找到比较详细的相关文档,有兴趣的可以搜索标题为"BMP文件结构的探索"的文章,可以在搜索结果中找到一个WORD文 ...
- 利用INF安装服务启动 及 浅析瑞星行为检测、360主动防御
序 2010年,反病毒(AntiVirus)与反-反病毒(Anti-AntiVirus)不论是从技术的深度.涉及的方方面面,又上升了一个层次. 行为防御.云安全技术等一些新技术不断的加入反病毒的行列, ...
- Mybatis配置信息浅析 MyBatis简介(二)
官方文档入门篇中有明确说明 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的. SqlSessionFactory 的实例可以通过 SqlSessionF ...
- TOLUA的文件结构
ToLua插件文件结构 1.BaseType:存放一些基础类型的绑定代码. 2.Core:提供的一些核心功能.包括封装的LuaFunction.LuaTable等等. 3.Editor:Extend文 ...
- Unity AssetBundle的打包 发布 下载与加载
码字不易,转载请注明出处哦 https://blog.csdn.net/newchenxf/article/details/124738469 1 前文 都2022了,为什么还讨论AB包?不是有Add ...
- Smack核心机制浅析
Smack核心机制浅析 在以上几篇博客中,我已经阐述了有关Smack技术的一些知识和要点,但是没有把Smack最精华的部分展示出来,由于本人学疏才浅,在阐述的过程中不免有这样那样的问题和诟病,但本人还 ...
最新文章
- uc3842改可调电源教程_明纬开关电源改可调详细教程
- 为什么 0.1 + 0.2 = 0.300000004
- 群签名和环签名的区别_Monero技术详解(三):核心技术—环签名(1)
- Handler 、 Looper 、Message
- 总结C#语言命名规范 (转)
- 插件前奏-android黑科技 hook介绍
- SQL获取当前时间的前10天
- 动力学系统simulink建模分析
- 无线摄像头接有线如何改协议_WiFi中继器——让无线传输更简单
- 九、多线程(高琪java300集+java从入门到精通笔记)
- html打开ppt自动播放,ppt文件怎么打开就可以全屏自动播放
- 四层PCB核心板制作6——BGA引脚扇出与电路扇孔
- sqlserver:关于timestamp时间戳 rowversion
- Cjson 库的使用
- 华为云服务器 共享文件夹在哪个文件夹,用户数据安全存储 华为云空间这些功能大显身手...
- 计算机软件的英文翻译,软件的英文翻译
- 2011年国家质监局公布女生禁用以下化妆品系列,女生一定要...
- 精彩的人生早已开始,看你怎么看待你的人生了
- NAND FLASH 和NOR FLASH
- 大智精英汇:赤裸裸的解刨创业的思路