壓縮方式:
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 |
