UnityのAssetBundleの実装をまとめました。
ハック用のコードもつけたいけど書くと長いので割愛。
最初に、AssetBundleとは?
Unityで作成したアプリにコンテンツの追加を行う機能です。
利用目的
iTunesStoreではWiFi以外からのダウンロードに50Mのサイズ制限があるのと、待ち時間のあるアプリ審査をせずにコンテンツの追加を行うのにAssetBundleを利用しています。
実装
- 起動時にCaching.readyとCaching.enabledがONになるまで待つ
- アプリ -> サーバーから最新のバージョン番号のみをJSONで取得
- アプリ内のAssetBundleバージョンより新しいバージョンの場合、サーバーからAssetBundleのファイル名、version、CRC32をJSON+tsvで取得※1
- 最新バージョンが有るAssetBundleをLoadFromCacheOrDownloadで取得
- ダウンロード後使わないAssetBundleはLoadFromCacheOrDownloadのCRCに偽の情報をセットして削除※2
まだ使うAssetBundleはCaching.MarkAsUsedで保存期間延長。- 処理が全て完了したら、最新のAsssetBundleバージョンを保存とtsvをplayerprefsに保存※3
※1 CRC32はUnity 4.2はログから回収が必要。v4.3では関数で返ってくる。v4.2用にPHPサンプルコード記載
※2 Unity4.2ではCachingの削除機能がないので、削除する為の裏技。
※3 tsvで受けたデータをplayerprefsに保存してます。playerprefsは起動時に全部読んでからでないと起動しないはずなので、保存方法は今後変更します。
※4 Caching.readyとCaching.enabledがONになるには、Cacheが多くなると遅い。
他にAssetBundleのchache保存期間が過ぎてから起動する場合も考慮して10日に一度cacheが存在するかチェックしてます。 これはやめた。無ければ都度ダウンロードする実装(リトライ機能あり)にした。また、Cacheが多くなると遅くなることもあり、最初に一括で落とさないで必要となるファイルのみダウンロードに変更した。
- CRC32
$path = "pathto/Library/Caches/Unity/DefaultCompany_xxx/xxx/CAB-xxx";
$str = file_get_contents($path);
$checksum = hash("crc32b", $str);
echo $checksum . "\n";
string crc = "xxxx";
uint crcUint = Convert.ToUInt32(crc,16);
WWW www = WWW.LoadFromCacheOrDownload (pathto, 1 ,crcUint);
これだけではない
ダウンロードの実装以外にアプリ内のリソースの管理や、例外処理も必要で何かとめんどくさい。
サーバー側の実装にビルド処理にシリアライズ問題と開発リソースに余裕がないと無理ゲー。
アプリの申請中はAssetBundleを別で管理したりと運用も考えるとほんと大変。
使わないですめば何よりです。
CRCの取得はバグあったので書いておく
CRCの取得は一部のAssetBundleは問題ないけど、大半は違う値になりましたorz
正しい取得方法はシーンからAssetBundleをダウンロードするか、ビルド時にCRCを取得することになります。
ダウンロードしてAssetBundleのCRCを取得
UnityEditorからiOSとAndroidの両方のAssetBundle CRCの取得が可能です。
WWW.LoadFromCacheOrDownloadの第三引数に異なるCRCを入れるとLogにエラーとして出力されたCRCを回収で対応となります。