App slicing はiOSプラットフォームでとても役に立ちます。この機能は開発者により多くのアセットを最初のアプリケーションバンドルに含めることを可能にしつつも、100MB以内にアプリを抑えることでWifi環境でなくてもダウンロードを可能にできるからです。この目的に沿うために開発者はApp Slicing と対応するもう一つの機能であるオンデマンドリソースを使うこともできます。オンデマンドリソースについては前回のブログ記事で解説しました。しかしながらオンデマンドリソースを使うにはアプリケーションはダイナミックにリソースをダウンロードするように対応する必要があり、必ずしも都合よくそのようにできたり、あるいは最適な選択であるとは言えない場合があります。また、全体的に複雑さを増してしまう点もあります。App Slicingにはこうしたデメリットがありません。
App Slicing には2つの特色があります:アプリケーション実行バイナリのスライシングとアプリケーションリソースのスライシングです。前者はアプリケーションバンドルから不要な実行バイナリを除去する機能で、iOS/tvOS 9.0以降をターゲットにしたアプリケーションをApp Storeに登録すると自動的にその処理が行われます。後者は不要なアセットを除去する機能で、これを使うには開発者の作業が必要となります。このブログ記事ではアプリケーションリソースのスライシングについてカバーします。
アプリケーションリソースのスライシングの第一目標は、同じアセットのバリエーションを内包することで無駄に消費されてきたディスクスペースやバンド幅を最適化することです。なぜあるアセットを複数のバリエーション持たなければならないかというと、今現在使用されているiOSデバイスについて古いものから新しいものまでを広くサポートする時、デバイス間でできることに大きな違いがあるためです。大体の場合ではデベロッパーは異なる品質のアセットを用意することで、他のデバイスへの影響を回避しながら、一番高速なデバイスで美しく動作することを実現します。iOS 9.0以前では、すべてのアセットのバリエーションはメインアプリケーションバンドルに含まれていなければなりませんでした。実際にはすべてのバリエーションのうち特定のデバイスで使われるのは一つだけなのですが、この制限がデバイス上のストレージやダウンロードのバンド幅を圧迫し、無駄に多く使わせることにつながっていました。
アプリケーションリソースのスライシングを導入することで、アプリケーションバンドルから不要なリソースを取り除くことが可能となります。
アプリケーションのリソーススライシングを活かす最も簡単なやりかたはアセットバンドルを使うことです。アセットバンドルをつかえばアプリケーションのアセットをスライシングに適した形に配置することができます。アセットバンドルはUnityに統合されており、パフォーマンスは通常のアセットデータファイルをロードするのと同じになるよう最適化されています。アセットバンドルはオンデマンドリソースのためのバックエンドとしても利用されるので、オンデマンドリソースの機能をすでに導入しているアプリでサイズの軽量化(App thinning)を行ったり、またその逆を行うのが簡単になるというメリットもあります。いちどアセットバンドルを設定したら、アプリケーションリソースのスライシングを導入するために必要なのは、いくつかのちょっとした変更だけです。この変更は下記のコード例で解説します。なお、このブログ記事ではアセットバンドル自体についてはカバーしません。もしこのブログ記事でアセットバンドルについて初めて目にした場合は、この資料 が助けになるでしょう。
アプリケーションリソースのスライシングを使うには、開発者はどのデバイスがどのリソースのバリアントを使えるかということについてリソーススライシングで使うすべてのバリアントに対して設定し、そしてアプリケーションの起動時にそれらのアセットをロードするように処理する必要があります。通常の(Xcodeを使った)iOSアプリケーション開発では、これはデータセットやイメージセットのアイテムをアセットカタログで作成し、device variationsをセットアップしてプレースホルダーのUIにリソースを割り当てることで行います。Unityでは、開発者はアセットバンドルのバリアント(variants)を作ることで対応します。バリアントとは同じアセット群を保持する複数のアセットバンドルのことで、実際に保持しているアセットそのものは異なるデータにできる仕組みのことです。アプリケーションのリソーススライシングに使用するアセットバンドルのバリアントはUnityEditor.iOS.BuildPipeline.collectResources
コールバックAPIを使って登録される必要があります。その後、的確なデバイス要求がPlayer SettingsのUIで設定されます。
最後に、開発者はアプリケーションの起動時にAssetBundle.CreateFromFile APIをつかってマニュアルでアセットバンドルをロードする必要があります。
アプリケーションのリソーススライシングに使うリソースを登録するエディタースクリプトの例:
using UnityEditor.iOS; #if ENABLE_IOS_APP_SLICING public class BuildResources { [InitializeOnLoadMethod] static void SetupResourcesBuild() { UnityEditor.iOS.BuildPipeline.collectResources += CollectResources; } static UnityEditor.iOS.Resource[] CollectResources() { return new Resource[] { new Resource("asset-bundle-name").BindVariant("path/to/asset-bundle.hd"), "hd") .BindVariant("path/to/asset-bundle.md"), "md") .BindVariant("path/to/asset-bundle.sd"), "sd"), }; }
アセットバンドルを起動時にロードする例:
var bundle = AssetBundle.LoadFromFile("res://asset-bundle-name"); // AssetBundle APIs を使ってアセットをロード // あるいは Application.LoadLevel でシーンをロード var asset = bundle.LoadAsset("Asset");
アセットバンドルとアプリケーションのリソーススライシングを実現する最も簡単な方法はこちらのBitBucketで公開されているAsset Bundle Manager デモプロジェクトを使うことです。ランディングページにはこのデモを理解したり活用するための詳細な解説が載っています。