亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Unity3D中assetbundle格式的示例分析

發布時間:2021-12-04 15:23:18 來源:億速云 閱讀:357 作者:小新 欄目:大數據

這篇文章將為大家詳細講解有關Unity3D中assetbundle格式的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

Unity3D 的 asset bundle 的格式并沒有公開。但為了做更好的差異更新,我們還是希望了解其打包格式。這樣可以制作專門的差異比較合并工具,會比直接做二進制差異比較效果好的多。因為可以把 asset bundle 內的數據拆分為獨立單元,只對變更的單元做差異比較即可。

網上能查到的資料并不是官方給出的,最為流行的是一個叫做 disunity 的開源工具。它是用 java 編寫的,只有源代碼,而沒有給出格式說明(而后者比代碼重要的多)。通過閱讀 disunity 的代碼,我整理出如下記錄:


asset bundle 分為壓縮模式和非壓縮模式。壓縮模式僅僅是用開源的 lzma 庫 對整個非壓縮包做了一次整體壓縮。壓縮數據的頭有 13 個字節,前 5 個字節是 lzma 解壓縮的 API 需要穿入的 props ,接下來的 4 字節是解壓縮后的數據庫長度。最后 4 字節不用理會它。

把壓縮數據解開后,就和非壓縮模式沒有差別,下面只討論非壓縮格式:

assert bundle 的文件頭是從這樣一個數據結構序列化出來的。

struct AssetBundleFileHead {
     struct LevelInfo {
          unsigned int PackSize;
          unsigned int UncompressedSize;
     };

     string          FileID;
     unsigned int     Version;
     string          MainVersion;
     string          BuildVersion;
     size_t          MinimumStreamedBytes;
     size_t          HeaderSize;
     size_t          NumberOfLevelsToDownloadBeforeStreaming;
     size_t          LevelCount;
     LevelInfo     LevelList[];
     size_t          CompleteFileSize;
     size_t          FileInfoHeaderSize;
     bool          Compressed;
};

string 是直接以 \0 結尾的字符串,順序序列化;size_t 是大端的 4 字節數字;bool 是單個字節;vector 就是順著排列的結構。

根據 Unity 版本的不同,assert bundle 的格式也不完全相同。Version 指明了 bundle 的格式版本,從 Unity 3.5 開始到 4.x 版都使用 Version = 3 ,下面只討論這個版本。HeaderSize 應該恰好等于以上這個文件頭的數據長度。

一個 assert bundle 是由多個 asset 文件打包而成,接下來順序打包了這些 asset 。序列化成這樣的結構:

struct AssetFileHeader {
     struct AssetFileInfo {
          string name;
          size_t offset;
          size_t length;
     };
     size_t FileCount;
     AssetFileInfo     File[];
};

這樣我們就可以分解出被打包在一起的多個 Asset 了(大多數情況下只有一個)。offset 表示的是除去 HeaderSize 后的偏移量。我們可以用 HeaderSize 加上那個部分的 offset 得到這個部分相對于整個 bundle 的文件偏移。

對于每個 asset ,又有它自己的數據頭。數據頭除了基本的數據頭結構 AssetHeader 外,還有額外的三個部分。disunity 把它們稱為 TypeTree ObjectPath 和 AssetRef 。注意:這里 Format 隨不同 Unity3D 的版本有所不同,我們只關心目前的版本的格式,這里 Format 為 9 (其它版本的格式,在大小端等問題上有所不同)。

struct AssetHeader {
     size_t TypeTreeSize;
     size_t FileSize;
     unsigned int Format;
     size_t dataOffset;
     size_t Unknown;

Unity 對 Asset 數據做了簡單粗暴的序列化操作。整個序列化過程是針對每種對象的數據結構進行的。TypeTree 是對數據結構本身的描述,通過這個描述,就可以反序列化出每個對象。

AssetHeader 后面緊跟著的就是 TypeTree 。但是,這個 TypeTree 對于 asset bundle 來說是可選的,因為數據結構的信息可以事先放置在引擎中(引擎多半只支持固有的數據類型)。在發布到移動設備上時,TypeTree 是不打包到 asset bundle 中的。

每個 asset 對象,都有一個 class id ,可以在 TypeTree 中查到如何反序列化。class id 的和具體類型的對應關系,在 Unity3d 的官方文檔 可以查到。但若我們只是想將差異比較在對象一級進行(而不是具體比較對象中具體的屬性),那么就不需要解開具體對象的細節信息,這部分也不用關心。所以這里也不展開(有興趣可以讀一下 disunity 的代碼,格式并不復雜)。

在 AssetHeader 中的 TypeTreeSize 指的就是 TypeTree 部分的大小。接下來是每個 AssetObject 的描述數據。

struct ObjectHeader {
     struct ObjectInfo {
          int pathID;
          int offset;
          int length;
          byte classID[8];
     };
     int ObjectCount;
     ObjectInfo Object[];
};

這里,所有的 int 都是以小端編碼的 4 字節整數(不同于外部文件格式采用的大端編碼)。在 Unity3D 中,每個對象都有唯一的字符串 path ,但是在 asset bundle 里并沒有直接保存字符串,而是一個 hash 過的整數,也可以看成是對這個對象的索引號。真正的對象放在數據頭的后面,偏移量為 offset 的地方。

這里的 offset 是相對當前 asset 塊的。如果想取得正確的相對整個文件的位置,應該是文件的 HeaderSize + asset 的 offset + asset 的 dataOffset + 這里的 object offset 。


接在 ObjectHeader 后的是 AssetRef 表,記錄了 Asset 的引用關系。用于指明這個 bundle 內 asset 對外部 asset 的引用情況。AssetRefTable 結構如下:

struct AssetTable {
     struct AssetRef {
          byte GUID[8];
          int type;
          string filePath;
          string assetPath;
     };
     int Count;
     byte Unknown;
    vector Refs;本文分享自微信公眾號 - Unity3D游戲開發精華教程干貨(u3dnotes)。

關于“Unity3D中assetbundle格式的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

秀山| 广南县| 遂溪县| 万山特区| 仲巴县| 青神县| 双柏县| 融水| 青海省| 剑河县| 茌平县| 阿尔山市| 威宁| 法库县| 高雄县| 方山县| 忻城县| 崇礼县| 元氏县| 米泉市| 周宁县| 枣阳市| 皮山县| 高雄市| 平顺县| 元氏县| 日喀则市| 称多县| 陇南市| 万山特区| 黔西县| 卢氏县| 龙川县| 沭阳县| 鲜城| 宁明县| 乌拉特后旗| 榆树市| 大英县| 四子王旗| 钟山县|