【Unity】AssetBundleの更新判定を行うAssetFileHashとTypeTreeHashについて

AssetBundleの更新判定を行うAssetFileHashとTypeTreeHashについてまとめました。

Unity2019.2.6

はじめに

AssetBundleをビルドすると、各AssetBundleと同名の.manifestファイルが生成されます。
この中にはAssetFileHashとTypeTreeHashという二つのハッシュ値が書き込まれています。

f:id:halya_11:20191018011247p:plain

AssetBundleをビルドする際には、この両方が変更されていなかったらビルドがスキップされます(インクリメンタルビルド)。
非常に便利な仕組みなのですが、これらの値がどう求められているのか、という情報が少なくブラックボックス化しています。

そこでこの記事ではAssetFileHashとTypeTreeHashについて少し具体的に検証してみます。

シリアライズされた値を変更してみる

それではまず、シンプルにPrefabが一つだけ含まれたAssetBundleをビルドします。

f:id:halya_11:20191018012241p:plain

ハッシュ値はこんな感じになりました。

f:id:halya_11:20191018012303p:plain

次にシリアライズされた値を少しだけ変えて、再度ビルドしてみます。

f:id:halya_11:20191018012339p:plain

ハッシュ値は下記のようになり、AssetFileHashだけが変更されました。

f:id:halya_11:20191018012357p:plain

シリアライズされるフィールドを増やしてみる

次に、前節のPrefabにコンポーネントExampleをアタッチします。
フィールドが一つだけシリアライズされています。

f:id:halya_11:20191018012714p:plain

まずこの状態でビルドします。
結果は下図のようになりました。

f:id:halya_11:20191018012656p:plain

次に、コンポーネントExampleを編集してシリアライズされるフィールドを増やします。

f:id:halya_11:20191018012816p:plain

結果は以下のように、今度はTypeTreeHashだけが変化することが確認できました。

f:id:halya_11:20191018012833p:plain

AssetBundleにコピーしたAssetを追加してみる

さて次に、前節のPrefabをコピーして、それを同じAssetBundleに含めてみます。

f:id:halya_11:20191018013800p:plain

これをビルドすると以下のような結果になります。
前節の結果と比べると、AssetFileHashだけが変更されていることがわかります。

f:id:halya_11:20191018013415p:plain

新しい種類のスクリプトがアタッチされたAssetを追加してみる

さてそれでは前節の状態からさらに、今度はコピーではなくBoxColliderがアタッチされたAssetを追加してみます。

f:id:halya_11:20191018014029p:plain

こんな感じです。

f:id:halya_11:20191018014131p:plain

この状態でビルドすると、以下のような結果が得られます。
前節の結果と比較すると、AssetFileHashとTypeTreeHashの両方が変化していることがわかります。

f:id:halya_11:20191018013525p:plain

まとめ

ここで一度これまでの結果をまとめます。

やったこと 変化するハッシュ
シリアライズされた値を変更 AssetFileHash
シリアライズフィールドを増やす TypeTreeHash
同じ構成のアセットをAssetBundleに追加 AssetFileHash
全く異なるアセットをAssetBundleに追加 AssetFileHash
TypeTreeHash

この結果から、まずAssetFileHashはシリアライズされた値に変更が加わったり、
AssetBundleに含まれるAssetが増減したときに変わると言えそうです

これに対しTypeTreeHashはシリアライズされるフィールドの種類が増えると変わります。
マニュアルには以下のように書いてあります。

これはUnityの新バージョンで発生するかもしれません(バグフィックスを除いて)。さらにMonoBehaviourでアセットバンドルに含まれるシリアイズされたフィールドを追加,削除した場合も同様に発生します。
Unity - マニュアル: アセットバンドル FAQ

Unityのバージョンアップ時にもシリアライズされるフィールドが変わりうるのでTypeTreeHashも変わりうるようです。

AssetFileHashは更新日時を変えたりLibraryを消すと変わってしまう?

AssetFileHashについて調べていると、ファイルの更新日時が変わると変化したり、
Libraryフォルダを消すと変化してしまうという情報が出てきます。

tsubakit1.hateblo.jp

http://sassembla.github.io/Public/2018:09:02%2010-17-07/2018:09:02%2010-17-07.html

これらについて検証するため、System.IO.File.SetLastWriteTimeで更新日時を変えたり、
ライブラリフォルダ消して再起動したりしてみましたが、手元の環境では再現しませんでした。

このあたりはブラックボックスな割にいつのまにかアップデートされていそうな雰囲気だし、
その割にビルドワークフローを構築する上で非常に重要な挙動なのでご自身の環境で検証することをお勧めします。

参考

Unity - マニュアル: アセットバンドル FAQ

tsubakit1.hateblo.jp

http://sassembla.github.io/Public/2018:09:02%2010-17-07/2018:09:02%2010-17-07.html