ビルトインプロファイラーでのパフォーマンス測定
物理演算のパフォーマンス最適化

ビルドした iOS プレイヤーのサイズ最適化

プレイヤーのサイズを削減する 2 つの主な方法は、Xcode の Active Build Configuration と、Unity の Stripping Level を変更する方法です。

リリースモードでビルド

完成版のリリース用のビルドは、Xcode 4.x/5.x のコマンドの Product -> Archive で行われることを想定しています。このコマンドを使用すると、リリース設定でのビルドの作成すべてのデバッグシンボルの削除を確実に実行できます。 このコマンドを送った後、最近の Xcode は Organizer ウィンドウの Archives タブに切り替わります(手動で移動するには、Window -> Organizer の順にメニューを選択します)。そちらには App Store size estimationDistribution の 2 つのとても便利な機能があります。 ビルドサイズ見積り機能はとてもよい働きをしますが、3G ダウンロードリミット (現在は 100MB) に設定する場合、エラーへの対策としていくらか余分なマージンを常に持っておくことをお勧めします。

iOS ストリッピングレベル

ストリッピング作業によるサイズの最適化は以下のように行われます。

  1. Strip assemblies : スクリプトのバイトコードが分析され、スクリプトから参照されないクラスやメソッドは DLL から削除されます。その結果それらを AOT コンパイルフェーズから除外することができます。この最適化によりメインのバイナリサイズや付随する DLL のサイズは削減され、リフレクションが使用されないかぎり問題ありません。

  2. Strip ByteCode : .NET DLL (Data フォルダーに保管) はストリッピングされてメタデータのみになります。これができるのは、すべてのコードが AOT フェーズですでにプリコンパイルされていて、メインバイナリにリンクされているためです。

  3. Use micro mscorlib : 特別で小さいバージョンの mscorlib が使用されます。いくつかのコンポーネント、例えば、Security、Reflection.Emit、Remoting、non Gregorian calendars、その他はこのライブラリから除かれます。さらに内部コンポーネント間の相互依存関係は最小限になります。この最適化によりメインバイナリや mscorlib.dll サイズを削減できますが、いくつかの System や System.Xml アセンブリクラスと互換性がないため慎重に使用してください。

これらのレベルは累積なので、レベル 3 の最適化は暗示的にレベル 1、2 を含み、レベル 2 は暗示的にレベル 1 を含みます。

注意: Micro mscorlib はコアライブラリが大きくストリッピングされたバージョンです。Unity で Mono ランタイムに必要なアイテムのみが残ります。micro mscorlib を使用するベストプラクティスは、アプリケーションで必要ない .NET のクラスや機能を使用しないことです。GUID などは、そのいい例です。GUID はカスタム作成された擬似 GUID で簡単に置き換えることが可能で、結果的によりよいパフォーマンスやアプリケーションサイズを得られます。

IL2CPP のストリッピング

IL2CPP のスクリプティングバックエンドが使用されるとき、Strip ByteCode と同等のものが常に利用可能です。この場合、Stripping Level のオプションは Strip Engine Code という名前の Boolean オプションに置き換えられます。このオプションを有効にすると、Unity Engine コードで使用されないモジュールとクラスは削除されます。逆に無効にすると、Unity Engine コードのモジュールとクラスのすべてが保存されます。

link.xml ファイル(後述)を使用すると、型とフルアセンブリを保存することによって効果的にバイトコードのストリッピングを無効にすることができます。例えば、System アセンブリがストリップされるのを防ぐため、以下のような link.xml ファイルが使用されます。

<linker>
       <assembly fullname="System" preserve="all"/>
</linker>

注意: アセンブリ全体を保存する能力は IL2CPP スクリプティングバックエンドにのみ適用されます。

ヒント

リフレクションを使用するときのストリッピングの対応方法

ストリッピングは静的なコード分析に強く依存していて、特に、リフレクションのように動的な機能が使用される場合、効率的に行えないことがあります。そのような場合、どのクラスを対象外とするかの情報をヒントとして渡す必要があります。Unity ではプロジェクト単位のカスタム化されたストリッピング_ブラックリスト_が可能です。ブラックリストの使用はいたって簡単です。link.xml ファイルを作成して Assets フォルダー (または、Assets のサブディレクトリ) に置くだけです。link.xml の記載例は以下のとおりです。リストアップされたクラスはストリッピングされることはありません。

<linker>
       <assembly fullname="System.Web.Services">
               <type fullname="System.Web.Services.Protocols.SoapTypeStubInfo" preserve="all"/>
               <type fullname="System.Web.Services.Configuration.WebServicesConfigurationSectionHandler" preserve="all"/>
       </assembly>

       <assembly fullname="System">
               <type fullname="System.Net.Configuration.WebRequestModuleHandler" preserve="all"/>
               <type fullname="System.Net.HttpRequestCreator" preserve="all"/>
               <type fullname="System.Net.FileWebRequestCreator" preserve="all"/>
       </assembly>

       <assembly fullname="mscorlib">
               <type fullname="System.AppDomain" preserve="fields"/>
               <type fullname="System.InvalidOperationException" preserve="fields">
                       <method signature="System.Void .ctor()"/>
               </type>
               <type fullname="System.Object" preserve="nothing">
                      <method name="Finalize"/>
               </type>
       </assembly>
</linker>

プロジェクトには複数の link.xml ファイルを含むことが可能です。各 link.xml ファイルは、多数のオプションを指定することができます。

assembly 要素は、管理されたアセンブリを示していて、ネストしているディレクティブがこれに当てはまります。 type 要素は、特定の型の処理方法を示すのに使用されます。assembly の子要素でなければなりません。fullname 属性には、1つ以上の文字にマッチするワイルドカード ’’ を使用できます。 preserve 属性は、以下の 3つの内 1つを使用できます。 * all : 指定された type のすべてを保持します(または IL2CPP に関してのみ、アセンブリ)。 * fields : 指定された type の field のみを保持します。 * nothing : 指定された type のみ保持しますが、その内容は保持しません。 * method の要素は、特定の関数が保持される必要があることを示しています。それは type 要素の子でなければいけません。関数は、名前かシグネチャで特定できます。

ストリップされたアセンブリは、プロジェクトの Temp ディレクトリ下のディレクトリに出力されます (正確な場所は対象のプラットホームによって異なります)。オリジナルのストリップされていないアセンブリは、ストリップされたアセンブリと同じ場所にある not-stripped ディレクトリで利用可能です。ILSpy のようなツールは、ストリップされた、または、されなかったアセンブリを検証し、コードのどの部分が削除されたか判断するために使用できます。

注意: どのクラスが、アプリケーションに必要とされているのに誤ってストリッピングされてしまったか判断するのか難しい場合があります。シミュレーターでストリッピングされたアプリケーションを実行し Xcode コンソールのメッセージをチェックすると、有用な情報が得られることがしばしばあります。

ディストリビューションをできる限り最小化する簡単なチェックリスト

  1. アセットを最小化します: テクスチャで PVRTC 圧縮を有効化し解像度をできる限り下げます。さらに未圧縮音声の数も最小化します。ファイルサイズの削減についての追加ヒントは こちら を参照してください。
  2. iOS の Stripping Level を Use micro mscorlib に設定します。
  3. Script Call Optimization を Fast but no exceptions に設定します。
  4. コードの中で System.dll や System.Xml.dll に存在するものは一切使用しないでください。これらのライブラリは micro mscorlib と互換性が ありません
  5. 不要なコードの依存関係を取り除く。
  6. API Compatibility Level に .Net 2.0 subset を設定します。.Net 2.0 subset は他のライブラリと限られた互換性しかないことに注意してください。
  7. JS 配列は使用しないでください。
  8. 値型 (構造体も含む) との組み合わせでジェネリックコンテナを使用することは避けます。

Unity でアプリケーションはどれぐらい小さくできますか。

空プロジェクトはサイズ最適化をすべてオフにすると App Store で 22MB 未満です。コードストリッピングを使用すると、メインカメラのみの空のシーンは App Store でおよそ 12MB 未満に縮小できます (zip や DRM 設定)。

App Store でリリースした後にアプリサイズが増加したのはなぜでしょう。

アプリをパブリッシュするときに Apple Store では最初にバイナリファイルを暗号化して zip を使用して圧縮します。暗号化によってコードセグメントがよりランダムになり、圧縮の条件が悪くなります。上記の「リリースモードでビルド」を参考にして、提出する前に App Store サイズを見積もる方法を確認してください。

ビルトインプロファイラーでのパフォーマンス測定
物理演算のパフォーマンス最適化