Unity 5.3.xのUnityFSの構造

Common
AssetBundleヘッダー

以下を順番に処理

  • signature(cstring): UnityRaw|UnityWeb|UnityFSなど. 基本的にこの3つのどれか.
  • format_version(int32): 6など. ファイルのバージョン.
  • unity_major_version(cstring): 5.x.xなど.
  • unity_version(cstring): 5.3.4p6など.
  • file_size(int64): ファイルサイズ.
  • ciblock_size(uint32): アセット情報のサイズ.
  • uiblock_size(uint32): lz4読み込み用アセット情報のサイズ.
  • flags(uint32): 圧縮フラグ.
  • compression_type: (flags & 0x3f) => 0: なし, 1: LZMA, 2: LZ4, 3: LZ4HC, 4: LZHAM.
Block
  • (int32): Unknown.
  • (int32): Unknown.
  • (int16): Unknown.
Node
  • offset(int64): AssetBundleヘッダーの位置からのオフセット.
  • size(int64): Nodeのサイズ.
  • (int32): Unknown.
  • name(cstring): Node名. CAB-abcdefgxxxxxなど.
5.3.3

(書きかけ)

5.3.4

  • Blockが格納されている箇所までseekする. file_size - ciblock_size.
  • ciblock_size分read. 変数をblocks_containerとする.
  • compression_typeNONEの場合はそのままblocks_containerを利用する. 変数をblocks_containerとする.
  • compression_typeNONE以外の場合は更にuiblock_size分readして伸張する. => 変数をblocks_containerとする.
  • blocks_container.guid(16bytes): Unknown. たぶんGUID.
  • blocks_container.num_blocks(int32): Blockの数.
  • blocks_container.num_blocks分繰り返しBlockを処理する.
  • blocks_container.node_blocks(int32): Nodeの数.
  • blocks_container.node_blocks分繰り返しNodeを処理する.

これで格納されているファイルの情報をパースできる.

ファイルを抽出する場合はAssetBundleヘッダーの最後尾へseekしたあとNode.offsetからNode.size分readすればよい.

LZ4|LZ4HCなどの圧縮が行われている場合はそれを伸張する必要がある.

tips
  • big endianで処理する.
  • cstringは0x00に到達するまでreadし続ける.
リポジトリ

https://github.com/PyYoshi/UnityAssetTools