Unityで出力したipa, apkの容量を削減するためのチェックリスト

この記事は [Akatsuki Advent Calendar 2017](https://qiita.com/advent-calendar/2017/aktsk) の 6 日目の記事です。
5日目: [Pythonでお手軽・異常検知 [ホテリング理論編]](https://qiita.com/Zepprix/items/f6a5de2e3f6689bd2c1f)

#### 背景
AppStoreでは本体の容量が150mbを超えるアプリはwifiを使わなければインストールできません(2017/12/06時点)[^1]。よって携帯網(LTEなど)でインストールできるようにするために容量を削減する必要があり、そのために過去にどのようなことをしたか、他にどのようなことをすれば効果があるかをまとめてみました。

---

###  現状把握
なぜアプリの容量が大きいのかを把握する。

#### Editor Logの起動
Unityのコンソールウィンドウの右上にあるメニューから Open Editor Log を選択する。
![diet_01.png](https://qiita-image-store.s3.amazonaws.com/0/177159/8dedf45b-26bf-58b5-9930-942753ba2369.png)


#### Build Log の確認
そのままビルドを行うと Editor Log にビルドのログが出力される。その中の Build Report を確認するとビルドアプリに対してどの程度アセットが使われているかの確認ができる。
アセットカテゴリごとの使用比率や、アセットごとの容量を確認できるので、何を減らしたら効率的に軽量化ができるかがわかる
経験則だが大体の場合はTexturesが原因で容量が大きくなることが多いので、画像アセットの整理、最適化で大体のアプリは軽くなる。

#### 出力サンプル
```shell-session
-------------------------------------------------------------------------------
Build Report
Uncompressed usage by category:
Textures      7.3 mb	 47.6% 
Meshes        0.0 kb	 0.0% 
Animations    0.0 kb	 0.0% 
Sounds        3.3 mb	 21.3% 
Shaders       221.9 kb	 1.4% 
Other Assets  7.3 kb	 0.0% 
Levels        6.2 kb	 0.0% 
Scripts       606.1 kb	 3.8% 
Included DLLs 3.9 mb	 25.6% 
File headers  25.1 kb	 0.2% 
Complete size 15.4 mb	 100.0% 

Used Assets and files from the Resources folder, sorted by uncompressed size:
 3.8 mb	 24.8% Assets/Resources/image_01.png
 3.1 mb	 20.0% Assets/Resources/image_02.png
 1.9 mb	 12.4% Assets/Sounds/bgm_02.mp3
 1.4 mb	 8.9% Assets/Sounds/bgm_01.mp3
 391.9 kb	 2.5% Assets/Resources/image_03.png
 222.2 kb	 1.4% Resources/unity_builtin_extra
 57.9 kb	 0.4% Assets/Resources/image_04.png
 4.1 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll
 4.1 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Standalone/UnityEngine.UI.dll
 1.8 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll
 1.8 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/Networking/Standalone/UnityEngine.Networking.dll
 1.5 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll
 1.5 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/Timeline/Runtime/UnityEngine.Timeline.dll
 0.9 kb	 0.0% Assets/Materials/Sample.mat
 0.7 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll
 0.7 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Runtime/UnityEngine.HoloLens.dll
 0.4 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll
 0.3 kb	 0.0% Packages/com.unity.ads@1.0.7/UnityEngine.Advertisements.dll
 0.1 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll
 0.1 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Runtime/UnityEngine.GoogleAudioSpatializer.dll
 0.1 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll
 0.1 kb	 0.0% /Applications/Unity2017_2_0f3/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Runtime/UnityEngine.SpatialTracking.dll
 0.1 kb	 0.0% Packages/com.unity.analytics@1.0.1/UnityEngine.Analytics.dll
 0.1 kb	 0.0% Assets/Scripts/Sample.cs
-------------------------------------------------------------------------------
```

---

### 軽量化
アプリの軽量化のために以下のことを確認する。

- 不要なアセットの削除
- 必要なアセットの軽量化
- 必要なアセットの外だし
- その他

### 不要なアセットの削除

#### 確実に利用していないアセットの削除
プロジェクトを綺麗に保つ意味でも現時点で確実に利用していないものがあれば消す。

- 開発時に利用していたダミーの素材
- 利用しているSDKのサンプルシーンに関するコード

#### Resourcesフォルダの整理
Unityはビルド時にそれぞれのアセットに対して参照があるかの確認を行い、利用しているものだけビルドに入れる機能を持っている。しかし、Resourcesフォルダに関しては参照の有無に関係なく全てビルドに含まれる。よってResourcesフォルダ以下に画像などを保存していた場合、それをアプリ内で利用していなかったとしてもビルドに含まれてしまう。
外部のアセットやSDKなどがResourcesフォルダを利用していて不必要なものが入っていた、なんてこともあり得るので一度はフォルダ名検索を行い、確認するのが良い。

#### StreamingAssetsフォルダの整理
これもResourceフォルダと同様に参照に関係なくビルドに含まれる、要確認。

#### 利用しているかどうか怪しいアセットの参照確認
不要なアセットを削除していく段階で使っているかどうか怪しいものがある場合はそのアセットがどこで利用されているかを確する。方法に関しては[kyusyukeigo](https://github.com/anchan828)さんが作成した[ReferenceViewer](https://github.com/anchan828/ReferenceViewer)がとてもよかった(Unity2017.2.0f3で簡易動作確認済み)。

##### ReferenceViewerの使い方
[リポジトリ](https://github.com/anchan828/ReferenceViewer)へ遷移してプロジェクトをクローン、もしくはzipダウンロードする。
![diet_04.png](https://qiita-image-store.s3.amazonaws.com/0/177159/c4e1e9a5-30d1-422d-48d7-9670255e8cb9.png)

リポジトリ内部にあるEditorフォルダをUnityプロジェクトにインポートする。
![diet_05.png](https://qiita-image-store.s3.amazonaws.com/0/177159/808aae48-9a46-03f2-88b3-4d97c7de61f4.png)

参照を確認したいアセットを選択し、Find Reference In Projectを選択する。
![diet_06.png](https://qiita-image-store.s3.amazonaws.com/0/177159/ec8ca6a5-244d-ec9b-63df-a982b2abb182.png)

結果
アセットの参照がどこにあるかわかった
![diet_07.png](https://qiita-image-store.s3.amazonaws.com/0/177159/ba64a024-3993-c00c-3b64-8679e74f231d.png)

### 必要なアセットの軽量化

#### 画像のサイズ確認
Unityにインポートされている画像のサイズを確認して無駄に大きなものになっていないかを確認する、アセットストアにあるような、PCでも遜色ないように表示されるように作成されたアセットなどははモバイルで利用するには大きすぎるテクスチャを持っていることがある。対応方法として、画像をツール等でリサイズしてインポートし直す方法もあるが、イメージのインスペクタからMaxSizeを設定してしまうのが簡単で良い。

![diet_08.png](https://qiita-image-store.s3.amazonaws.com/0/177159/58aad6b8-4d92-61ec-76a2-63c3be10fc72.png)

#### 画像、音声圧縮
アセットを圧縮することによって容量を削減する。
これもアセットのインスペクタから設定することができる。画像の圧縮方法はプラットフォームごとに変更できるので、表示を確認しながら最適な圧縮設定を行う。
iOSではPVRTC、AndroidではETC、もしくはETC2を使うことが多いような気がする
それぞれの圧縮形式に画像の得意、不得意があるのでその点は注意する。例えばPVRTCではアルファ持ちのテクスチャだと
アルファ周りが汚くなる傾向があり、アルファ情報と色情報を別々に持ってシェーダで合成して表示する、という方法が存在する。

画質、音質と容量両方ギリギリまで妥協できない場合は、外部ツールを使うこともある。

#### Sprite Editorのborder活用
uGUIでダイアログを表示する場合に枠の画像を原寸大で出さなくてもSprite EditorのBorderを利用すればより小さい画像でダイアログを表示できる。
例えば縁に色付けしただけの画像を表示させたい場合、以下のような画像を用意する。
![frame.png](https://qiita-image-store.s3.amazonaws.com/0/177159/1be34a21-6f49-3f63-b903-f059217621cc.png)

これをUnityにインポートして、インスペクタからSprite Editorを選択し、Borderを設定する。
<img src="https://aktsk.qiita.com/files/61fc693a-7b95-74c4-5e4f-33a6c7f946e7.png" width=40%>
Borderを適用した画像をuGUIのImageにセットして、Image Type を Slicedにするとサイズの違うウィンドウだと良い感じに表示される。
![diet_11.png](https://qiita-image-store.s3.amazonaws.com/0/177159/6507a6d7-c486-11b3-b4c2-6361945158a7.png)

<img src="https://qiita-image-store.s3.amazonaws.com/0/177159/f5307651-ed25-e551-c314-e977f54c3877.png" width=40%>

#### アトラスの活用
[Sprite Packer](https://docs.unity3d.com/ja/current/Manual/SpritePacker.html)や[Sprite Atlas](https://docs.unity3d.com/Manual/SpriteAtlas.html)などを利用して複数の画像を一枚にまとめることによって、描画コストを削減できるが、細かいUIをまとめてアトラス化したのちに圧縮をかけることによって容量を削減できる。個別のUIのサイズがバラバラでPVRTCなどで圧縮できない時に有効。

#### アセットバンドルによるアセットの外だし
Unityの[アセットバンドルシステム](https://docs.unity3d.com/ja/current/Manual/AssetBundlesIntro.html)を利用し、起動時に必要ないアセットを外部に出すことでアプリ本体の容量を削減することができる
#### その他
実際に試してはいないが、容量削減のために以下の方法がある

- メッシュ及びアニメーションの圧縮
- 利用するDLLの選択
- モバイル用 .NET Library のサイズ削減
- iOSビルドでのScript Call Optimizationを設定確認
- 利用している箇所が少ないフォントファイルの画像化
- App Slicing を行う

---

### Unityプロジェクトでのipa, apk削減のためのチェックリスト

- 参照されていないアセットの削除
- Resourcesフォルダの整理
- StreamingAssetsフォルダの整理
- 画像のサイズ確認
- 画像、音声圧縮
- Sprite Editorのborder活用
- アトラスの活用
- アセットバンドルによるアセットの外だし
- メッシュ及びアニメーションの圧縮
- 利用するDLLの選択
- モバイル用 .NET Library のサイズ削減
- iOSビルドでのScript Call Optimizationを設定確認
- 利用している箇所が少ないフォントファイルの画像化
- App Slicing を行う

### 参考
[Unity マニュアル ファイルサイズの削減](https://docs.unity3d.com/ja/current/Manual/ReducingFilesize.html)
[Unity、apkやipaの出力ファイルサイズ削減](https://ameblo.jp/sat-box2011/entry-12215674690.html)
[Unity アプリ容量を減らすための工夫](http://www.shibuya24.info/entry/2015/07/30/090000)
[App Slicing ](https://blogs.unity3d.com/jp/2015/12/28/optimizing-ios-app-size-with-resource-slicing/)

### 注釈
[^1]: [Higher Limit for Over-the-Air Downloads](https://developer.apple.com/news/?id=09192017b)