読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】AssetBundleのManifestファイルに書かれている内容について

f:id:tsubaki_t1:20160720224038j:plain

Unity5でAssetBundleを作成する際Manifestファイルが作成されるようになりました。

今回は、このManifestファイルは何というお話。

ManifestファイルはAssetBundleの構成情報が記述されている

.Manifestファイルは只のテキストファイルです。AssetBundleを作成する際に、アセットバンドルと同じパスに作成されます。

この.manifestファイル自体はゲーム実行時において何の役にも立たないので、ゲームに含めたりサーバーで公開する必要は無いです。
但し、ゲームを構築する上で幾つか重要な情報を持っています。「AssetBundleがどのように構成されているのか」という情報です。

 

テキストファイルなので当然のようにTextやメモ帳、ワードパットで開くことが出来ます。

f:id:tsubaki_t1:20160720224347j:plain

作ったデータを元に.manifestを記述しているので、manifestファイルを変更しても余り意味はありません。

生成したパスと同名のManifestにはAssetBundle同士の依存関係を記述

AssetBundleを作成すると、どのようなAssetBundleを作成したかに関わらず、AssetBundleを出力したフォルダと同名のAssetBundle及びAssetBundle.Manifestが生成されます。

f:id:tsubaki_t1:20160720225356j:plain

このAssetBundleにはAssetBundleの依存関係についての記述が書かれます。これを確認して、依存関係が合った場合、該当のAssetBundleをロードする際には依存先のAssetBundleもロードしておく必要がある事が分かります。

f:id:tsubaki_t1:20160720225640j:plain

例えば上記の場合、PrefabはEthanのAssetBundleに格納しているモデルを必要としているので、PrefabのAssetBundleはEthanのAssetBundleと一緒に読む必要があります。

assetbundleと同名のmanifestにはAssetBundleを構成する情報を記述

assetbundleを作成する際、assetbundleと同名のassetbundle.manifestが作成されます。例えばethanであればethan.manifest、prefabであればprefab.manifestといった感じです。

これらのmanifestには、assetbundleを構成する情報や、assetbundleを再構築するかどうか判定するためのデータが含まれます。

AssetFileHashとTypeTreeHashは、AssetBundleの更新判定

f:id:tsubaki_t1:20160720230713j:plain

AssetFileHashとTypeTreeHashは、主にアセットを更新する必要があるかどうかの判定にしようされているみたいです。

 

AssetFileHashはAssetBundleに含まれるアセットが変更されたり増減した際に変化するハッシュデータです。

例えば下のように、assetbundleに含まれるアセットの情報が変わると「assetbundleの情報が変化した」として再構築を行います。

f:id:tsubaki_t1:20160720231325j:plain

 

TypeTreeHashも似たような感じです。但し、script自体の変化ではなくシリアライズ出来るデータ群の変更、例えばpublic変数やserializeFieldの増減等により変化します。

少し分かりにくいので例です。
下の赤と青のコードは、Inspectorに露出してるデータに違いはありませんが内部の動作が異なります。この場合、TypeTreeHashは同一の値を表示しています。

逆に緑と青のデータはメソッドの処理こそ同一ですが、Inspectorに表示する内容が異なります。この時、TypeTreeHashが異なる値を表示しています。

f:id:tsubaki_t1:20160720232516j:plain

AssetFileHashとTypeTreeHashは上にも書いたとおり、AssetBundleの変更判定に使用されているみたいです。例えば、これらのハッシュ値が現在のハッシュ値と同一ならばAssetBundleのビルドはスキップされます。

 

なお、同一のAssetBundleの内容だからと言って、同一のハッシュ値になる訳では無いみたいです。どうもファイルの日付やOSで変化してるっぽいです。

ClassTypeには、AssetBundleが使用しているクラスを記述

少し面倒くさいのがClassTypeです。ここにはAssetBundleで使用しているクラスが指定されます。

例えば Class 4の場合、Class IDを確認するとTransform、Class 90はAvaterといった感じです。クラスIDは、YAML クラス ID リファレンスで確認出来ます。

f:id:tsubaki_t1:20160720233702j:plain

この情報が重要な理由は、Strip Engine CodeでUnityエンジン側のコードがストリップされてしまう可能性があるためです。

例えばゲームのデータやシーン情報は全てAssetBundleに格納しAssetBundleに配置したプレハブやシーンにてゲームを構築するとします。
この時、ゲームに最初から含めるシーンにはRigidbodyやRenderingに関する記述やデータが無かった場合、strip engine codeがonになっていると、ビルドしたプロジェクトからコード一覧が削減されている事があります。

 

これが顕著なのがWebGLで、全てのコードを全てストリップすると、WebGLビルドが生成したプロジェクトの.jsgzは2MB位まで小さくなります。

ストリップ問題の対策

ストリップ問題の対策は、こちらのAssetBundleにのみ使われているクラスがある場合の注意で紹介してます。
Could not produce class with ID とか出たら要注意で。iOS(il2cpp)の場合は落ちる事もあります。

tsubakit1.hateblo.jp

ClassIDが114でInstanceIDが0じゃない奴は要注意

厄介なのがclass IDが114のクラスです。この114はMonobehaviourクラスである事を指しているのですが、同時にエンジンコードでもあります。このため、使用していないのであればストリップされる事が望ましい…というかストリップされるコードです。

f:id:tsubaki_t1:20160721000940j:plain

この114のコードですが、field idはクラス名のmd4変換した物、guidはdllのguidに該当します。ストリップしたくないクラスは、一応、こんな感じで求められます。

やってる事はプロジェクト内の全クラスをMD4に変換して比較してるだけです。おお怖い怖い。

f:id:tsubaki_t1:20160721001536j:plain

f:id:tsubaki_t1:20160721001542j:plain

f:id:tsubaki_t1:20160721001549j:plain

gist.github.com

まぁ、適当に改造して使ってください。

もしコードがストリップされている場合は、ココを参考にlink.xmlを設定するなり、使用しているコードをプロジェクトに含めるなりすればOKです。

tsubakit1.hateblo.jp

 AssetsとDependenciesは、内包するアセットと依存先。但し…

最後にAssetsにはAssetBundleに含まれるアセット群が記述され、Dependenciesでは依存しているAssetBundleが記述されます。

f:id:tsubaki_t1:20160721001958j:plain

但し1点注意すべき点として、AssetBundleが直接参照しているアセットのみが記述される点があります。

例えばPrefabがMaterialを参照していた場合、AssetBundleにはMaterialやMaterialが参照しているシェーダーが含まれます。しかし、AssetBundleManifestにはMaterialやShaderについての記述はされません。

これが下のような問題を引き起こします。

tsubakit1.hateblo.jp

関連

forum.unity3d.com

docs.unity3d.com

tsubakit1.hateblo.jp