15/5/26 注意!: 記事を書いてる途中で気づきましたがこの記事は間違ってます。アセットバンドルのビルド+空のapkビルドの時間は普通にビルドする時間より大幅に長くなり、ビルド時間の短縮にはなりません。アプリをアセットバンドル対応させたい方には有用な部分も…ある…かも…?

Unityでゲームを作っていて、ビルドがなげーなと思った事はありませんか?
もう少しビルド待ちを短くする手段はないのでしょうか?
この記事ではUnity5で新しくなったAssetBundleシステムを利用してビルド時間短縮するアプローチに迫ってみます。

■はじめに

そもそもUnityの優れている所はイチイチビルドしなくてもプレイボタンを押すだけでゲーム実行をプレビューできるところです。
普段であればエディタ上でビルド待ち無しでトライアンドエラーできるわけで、ビルド時間の長さはリスクにはなりません。
しかし場合によっては実機で確認しないとチェックしようがない場合もあります。例えばAndroid固有のカメラやセンサ類を使う場合や特殊なデバイスを用いる場合。
私の場合はGearVRのアプリ制作で実際にGearVRをかぶって確認しないとどうしようもない状況でした。この記事ではこういったイチイチビルドしないといけなくてビルド待ちがクリティカルに開発進捗に影響してしまう状況の人を対象にしています。

※ちなみにGearVR開発の場合についてはOculusRiftDK2を用意すればエディタ上のプレイモードでどのように見えるか確認できるので、究極的には開発中はDK2のプレビューで済ませて最後のパブリッシュの時だけGearVR向けにビルドするという方法もあります。(私はOculusRiftを所持してないので他の方法を探してみました)

前提知識としてUnity5の新AssetBundleシステムについて、公開されたUnite2015の伊藤さんのセッション(ここが変わる!Unity 5のスマホ開発 ~アセットバンドル、ビルド、プラグイン~)を観ておいて頂くと理解がスムーズになるかと思います。
Unite 2015 Tokyo タイムテーブル/講演動画

■本論

Unityのビルドでは
1.プロジェクト内のスクリプトをコンパイル
2.ビルドセッティングでビルドに含めたシーンについて参照してるアセットを全てチェックしてパッケージ化
という2つのステップを行っています。(参考:http://japan.unity3d.com/developer/document/tutorial/basic/publish.html
この内スクリプトのコンパイルは削りようがないですし待ち時間も短いのでよしとします。
しかしアセットのパッケージ化には相当時間がかかりますし、なによりスクリプトをちょっと変えただけで何の変化もしてないアセット群を毎回イチからパッケージ化するのは理不尽だと思いませんか?
そうです、このAsset群のビルドをAssetBundleの方でやってアプリのビルドから分離してしまおうというのが今回の作戦です。

実際ビルド時間はどれくらいかかっているのか?例として以下のようなキャラが4人いて家や風景のあるメインシーンをビルドしてみます。
スクリーンショット 2015-05-25 23.56.51
結果は10分17秒。長い…長いです。イチイチ動作確認するたびに10分待たされるのはつらいものがあります。

ちなみに何もない空のシーンを作ってこれのみをビルドするとどうでしょう。
スクリーンショット 2015-05-25 23.33.32

結果は3分40秒でした。Plugins/Android以下のアセットはパッケージされてしまう事もあり、一瞬で終わるとはいきませんが、トライアンドエラーを繰り返す局面ではビルド時間は1秒でも短い方が嬉しいです。この3分40秒を目指していきましょう。

必要になるのは新AssetBundle用のUnityサンプルプロジェクトです。以下のリンクからダウンロードしてください。
http://files.unity3d.com/vincent/assetbundle-demo/users_assetbundle-demo.zip
このプロジェクトを開いてScriptForAssetBundleSystemフォルダとLoadScenes.csを自分のプロジェクトにドロップしてコピーします。
kiji1

次にメインシーンがAssetBundleとしてビルドされるようにするために、メインシーンファイルを選択してAssetLabelsにAssetBundle名を付けます。
kiji2

スクリプトを編集します。
Scriptの変更ではAssetBundleの再ビルドがかからないように、BuildScript.csでBuildAssetBundleOptions.IgnoreTypeTreeChangesを有効にします。
kiji3

LoadScenes.csでロードするメインシーンのassetbundle名とシーン名を指定します。
kiji4

これであとはメニューからAssetBundles→Build AssetBundlesを選べばメインシーンのAssetBundleの完成です。このAssetBundleにはメインシーン内で参照されている全てのアセットが含まれてます。ちなみにAssetBundleのビルド時間は4分30秒でした。

それではアプリからこのメインシーンのアセット群を除外してAssetBundleから読み込むようにしましょう。
先ほど作った空っぽのシーンに空のゲームオブジェクトを追加、このゲームオブジェクトにLoadScenes.csをアタッチします。
あとはビルドセッティングでビルドに含めるシーンをこの空っぽのシーンだけにすれば、シーンから参照してるアセットはほぼゼロとなりビルドされたapkにパッケージされるアセットも無くなります。

apkのビルドにはメニューからAssetBundles→Build Playerを選択します。Build Playerの実際の動きは
1.更新が必要なAssetBundleがあればビルドする
2.ビルドされたAssetBundleをStreamingAssetsフォルダにコピーする
3.apkをビルドする
という流れです。LoadScenes.csはデフォルト設定ではこのStreamingAssetsからアセットバンドルを読み込みます。
さて、問題のapkビルド時間ですが、この時点で3分30秒になりました!ブラボー!!
今後はスクリプトを編集しただけではAssetBundleのビルドはスキップされるので、ちょっとした調整ならビルド時間は短縮できるようになりました。
注意点としてはビルドされたapkを実行すると空っぽのシーンが始まりそこからAssetBundleロードが入るので十秒ほど待ちが入ります。それでもビルド時間の短縮を考えると分があります。

 

■結末