もんりぃ is undefined.

育児ネタとか、技術ネタとか。

AssemblyDefinition × AssetBundle の罠?

🌱 はじめに

📝 現象

Unity 2017.x 時代に作った AssetBundle が AssemblyDefinition 対応済の Unity 2018.1 ビルドから読み込めない。

🔍 調査

とにかく「AssemblyDefinition AssetBundle」でググる

ひたすらググる

すると、 フォーラムの記事 がヒットする。

この中で Unity の中の人の回答 に以下のような情報が。

To load scripts correctly in C#, we store assembly, namespace, and class information in the asset bundle: ...code... This means that any time you rename a class, move the class to a new namespace, move the code to a new assembly, or rename the assembly it is in, you will need to rebuild your asset bundles.

雑に訳すと「AssetBundle に Assembly, namespace, class の情報追加するようにしたから、 再構築して クレメンス」というコトらしい。

よろしい、ならば再構築だ。

🖋 前提

で、再構築の時の罠の話をする前に、キッズスターの AssetBundle 運用がどうなってるのかをザッとお伝えする必要があります。

キッズスターでは、「都度のビルド毎に生成される SingleManifest *1 をビルド毎にバージョニングして Amazon S3 にアップロードし、これを起動時にダウンロードさせる」「個別の AssetBundle については、AssetBundle ビルド時に AssetBundle のハッシュ値(AssetFileHash)をファイル名に して Amazon S3 にアップロードする」という運用をしています。

こうすることで、「アプリ側は SingleManifest のバージョンさえ間違えずにダウンロードできれば、個別の AssetBundle のバージョニングについて意識するコト無くダウンロードができる」状態が構築されています。

これは、言い換えると「AssetBundle 的に何らかの変化があった場合には、AssetBundle 本体はもちろんのこと AssetBundle の AssetFileHash も変化する ことを期待している」ということです。

さもなければ、ファイルが上書きされてしまい、「新しいビルドでは読めるが、古いビルドでは読めない」みたいなコトが起きてしまいます。

🕳 罠

で、まぁ、察しの良い読者の方はお気づきかと思いますが、今回の罠というのは「AssemblyDefinition 化したことにより追加される Assembly, namespace, class の情報は AssetBundle の AssetFileHash を変化させない 」というコトです。*2

つまり、「AssetBundle を再構築しないと AssemblyDefinition ビルドでは読めないが、再構築すると旧ビルドで読めなくなる」という 😱 な状況になるわけですね。

🏃‍♂️ 回避策

こりゃマズいというコトで回避策を id:fakestarbaby と一緒にあれやこれやと考えました。

結果出てきた案としては「何とかして AssetBundle の中身 *3 を変化させずに、新しい AssetFileHash を生成させる」というワークアラウンドでした。

最初は「ファイル名を変えて AssetBundle をビルドした後、再度ファイル名を戻してビルドし直す」という手段で行けたように見えましたが、「元 Asset が ScriptableObject の場合は、ファイル名を戻した後の AssetFileHash が元に戻ってしまう」という状況だったようです。

で、「こりゃ手詰まりか…!?」とか思って一晩寝かせたところ、翌朝に「 AssetBundle Variant を付けてビルドし、再度 Variant を外してビルドし直す 」というワークアラウンドを思いつき、試してみてもらったところ巧く行きました!

てことで、コレが現時点の答えのようです。

2018/06/21 11:34 追記:

どうやら「一度 Variant の付け外しを行えば AssetFileHash の再生成が行われる」っぽいです。付け外しの間にビルド挟まなくても良いっぽい。

2018/06/21 12:07 追記:

.metatimeCreated っていうフィールドを弄れば AssetFileHash が更新される」ことも判明しました。

アセットの内容と時刻をもとにハッシュが決まるみたいな情報を見かけたことがあるので、このフィールドがそれに該当するみたいですね。

ただ、このフィールドがどのタイミングで生成されるのか?がイマイチ分かりません…。

🤔 所感

  • AssetBundle 側の仕様バグだとは思いますが、まぁ、レアケースなんでしょーがない…のかな…?
  • 諦めなければ閃きは降ってきます。
  • なお、この時のやり取りは Slack のとある発言に対する Thread で行われていたんですが、その Reply の数をご覧いただければ大変さがご理解頂けるかと存じます。ご査収くださいませ。
    f:id:monry84:20180621112730p:plain

*1:AssetBundle 出力先ディレクトリに吐き出される AssetBundle

*2:稀に変化するモノもあったようですが、私が作業していたわけではないので、仔細は不明です…。

*3:というか、AssetBundle の内容物の情報