概要
基本的な最適化については「Unityアプリを高速・安定化するために見直すべき事を9選まとめてみた|Qiita」で網羅的に解説されています。
この記事は、このアプリ(Weather・天気予報アプリ)で使われている特殊な最適化手法です。
☆本記事に書かれている内容ーーーー
・不要な機能の無効化
・メモリ解放
・GPU/ストレージの最適化
--------------ーーー
不要な機能の無効化
Physics(物理演算)
物理演算機能は必要ないのでオフにします。
プログラムのStart関数を編集します。2Dの場合は”Physics2D.autoSimulation = false;”を使います。両方書く必要はありません。
void Start()
{
Physics.autoSimulation = false;
Physics2D.autoSimulation = false; //2Dの場合はこちらを記載
}
Audio(音声)
音声もオーバーヘッドの原因となるので使いません。図1に示すように、”Project Settings>Audio”でAudioManagerを開きます。
“Disable Unity Audio”にチェックを入れます(図2)。
メモリの解放
スクリプト
天気予報プログラムでは、図3に示すように、画像をダウンロードして読み込んでいます。
これをそのまま実装してみましょう。
プログラムを立ち上げて放置。タスクマネージャを観察すると、数ギガバイト単位でVRAMが占領されていることが発覚します(図4)。
原因は一つで、画像データのキャッシュが解放されていないためです。
Unityは動的に取得した、テキストデータ(JSON、xml)・画像(png、jpg)ファイルをResourcesに振り分けます。さらに、変数値を変更したとき、古い値をそのままメモリ上で保持しているケースがあります。
したがって、これらのキャッシュは明示的に開放する必要があります。実行は数分に一度で、基本はどこに書いても大丈夫です。ただし、ガベージコレクションやUnloadUnusedAssetsは重いため、間違ってもUpdate関数の中から呼び出さないようにしてください(※)。
//メモリを解放する
Resources.UnloadUnusedAssets(); GC.Collect();
※UnloadUnusedAssetsは実行に0.3~2秒かかります。AsyncOperationなので、処理が終わるまで待たされます。
ここでビルドしても十分に低負荷ですが、さらにパフォーマンスを切り詰めたいので、次節以降の設定も適用します。
最終的に、ここから図5のように、CPU・GPU負荷が半分以下になります。
GPU/ストレージの最適化
Quality(描画品質)
Project Settings>Quality。
ここは、Very LowやLowを参考に、ギリギリまで落とします。
適当な設定はアプリごとに違うため、自分で調べてほしいのですが、一点だけ落とし穴があります。
垂直同期の設定について、Don’t Sync(同期しない)にするというのが定説とされています。
しかし、自作PCのようにグラフィックボードを自前で揃えている端末の場合、ディスプレイとGPUのfpsが合わないことが稀によくあります。
このとき、GPUにもCPUにも結構な負荷がかかります。高性能PCであればあるほど、傾向は顕著です。
これを回避するため、垂直同期は”Every V Blank”もしくは”Every Second V Blank”に設定します。
もしくは、”Don’t Sync”を選択し、スクリプトでフレームレートを設定します。この場合はStart関数に次のコードを書きます。
Application.targetFrameRate = 60;
とくに、iOS向けアプリケーションの場合はデフォルトでフレームレートが30fpsに設定されているため、Android版と比べてなぜかカクカクするという現象が起こる場合があります。
したがって、iOS版での展開を視野に入れるなら、下の方法一択です。
Canvas(UIの分割)
要素に一か所でも変更が与えられると、Canvasは子のUIすべてに対してメッシュを再生成します。何の変化も無いUIを実現するのは難しいので、変化がある動的なCanvasと、変化のない静的なCanvasは分離します。
ビルドの選択
Windowsの場合、スクリプト・バックエンドとして、MonoとIL2CPPを選択できます(図7)。Project Settings>Player>Configurationで確認可能です。
IL2CPPの方がプログラムの動作は高速です。しかし、ファイルサイズには、370MB(IL2CPP)に対し、58.7MB(mono)と実に6倍以上の差が生じました。
今回のプログラムの場合、そこまでシビアな実行速度差を求めないので、monoを選択します。ビルド時間もIL2CPPの方が長くかかるのも大きな理由です。
再圧縮
Android向けのビルドで、さらにファイルサイズを削りたい場合、図9のようにapk(aab)の拡張子を一度、zipに変えます。
このファイルを展開し、中身をもう一度「7zip」でzip形式に圧縮します(図10)。
こうして出来たzipファイルの拡張子を、もう一度apk(aab)に戻します。すると、容量が1MB近くも減ったことが確認できます(図11)。
どうして容量が減ったのかは全く分かりません・・・