[Unity] ローカルデータでのAssetBundleとResourcesでローカライズ処理の比較

#内容
サーバーからダウンロードせずにローカルデータでローカライズするのに
AssetBundleとResourcesのどちらがよいかが分からなかったため比較した。

自分が使用するためのデータ比較なので公平性があるとは言い切れませんので参考程度に:grin:
また実データを使用しているのでプロジェクトは公開できません:confused:

プロジェクトを公開できるよにした版を用意しました。
詳しくは、
http://qiita.com/akerusoft/items/29a53a196c63e537a4b9

#結果
AssetBundleはオリジナルのものと読み込み速度が変わらないがメモリを多く消費する。
([別のテスト](http://qiita.com/akerusoft/items/29a53a196c63e537a4b9)結果によればUnloadのタイミングによってはメモリ消費量を抑えることがわかった)

Resourcesは初回の読み込み時間が早くて、
キャッシュされたあとの読み込み速度が遅い。
メモリの消費はさほど変わらない。

|  | Original[ms] | AssetBundle[ms] | Resources[ms] | Original(Memory) | AssetBundle(Memory) | Resources(Memory) | 
|--:|--:|--:|--:|--:|--:|--:| 
| 1 | 1,531 | 1,549 | 1,382 | 7,362,812 | 13,950,948 | 7,423,765 | 
| 2 | 472 | 835 | 686 | 7,369,878 | 13,971,275 | 7,431,003 | 
| 3 | 514 | 647 | 911 | 7,373,798 | 13,975,077 | 7,435,047 | 
| 4 | 386 | 430 | 783 | 7,377,714 | 13,983,085 | 7,442,723 | 
| 5 | 445 | 458 | 665 | 7,381,654 | 13,986,953 | 7,446,591 | 
| 6 | 448 | 416 | 647 | 7,385,522 | 13,990,941 | 7,450,415 | 
| 7 | 492 | 420 | 673 | 7,389,510 | 13,994,645 | 7,454,283 | 
| 8 | 461 | 428 | 779 | 7,397,166 | 13,998,633 | 7,458,031 | 
| 9 | 391 | 520 | 596 | 7,400,914 | 14,002,381 | 7,462,095 | 
| 10 | 429 | 402 | 742 | 7,404,950 | 14,006,249 | 7,465,799 | 
| Average | 557 | 611 | 786 | 7,384,392 | 13,986,019 | 7,446,975 | 
| Max | 1,531 | 1,549 | 1,382 | 7,404,950 | 14,006,249 | 7,465,799 | 
| Min | 386 | 402 | 596 | 7,362,812 | 13,950,948 | 7,423,765 | 
| Originalとの比較 |  |  |  |  |  |  | 
| Average |  | 1.09 | 1.41 |  | 1.89 | 1.01 | 
| Max |  | 1.01 | 0.90 |  | 1.89 | 1.01 | 
| Min |  | 1.04 | 1.54 |  | 1.89 | 1.01 | 

メモリの値はProfiler.GetTotalAllocatedMemory()
時間はSystem.Diagnostics.Stopwatch.ElapsedMillisecondsの値。


#環境
Unity 5.4.0p4
Windows10

実行環境
Android 4.0.4

ビルドはMonoでデバッグ情報は付加しないリリースビルドで。
(IL2CPPはAssetBundleのストリップ問題がおきると面倒だったので)


#データ
比較にあたってテストデータっぽいテストデータだと現実味のある値を見れないため
以前リリースしたアプリのデータを利用した。

以下の画面がオリジナルの画面となる。
![image](https://qiita-image-store.s3.amazonaws.com/0/36154/d6e3ee7d-d198-2754-3580-31618bc3578d.png)

テーブルビュー形式でセルは仮想セルで表示されている個数しか存在しない。
各セルに表示するどんぶりの画像は60枚ある。
だいたい160 x 160以内におさまっている。

食材のスプライトは73枚あるが640 x 512の1枚に収めている。

下記の画面が初期表示されるシーンで画面下部のボタンを押すと
さきほどのテーブルビューのシーンへ遷移する。
![image](https://qiita-image-store.s3.amazonaws.com/0/36154/c14578cd-9bd0-876f-790b-c7f27410beab.png)

このボタンを押してテーブルビューのシーンが表示されるまでの時間を計測した。

計測するMonobehaviourは一番最後に実行されるようにオーダーを設定。
![image](https://qiita-image-store.s3.amazonaws.com/0/36154/f4ba2922-4130-3c3a-bc94-ea5a7563d077.png)

この状態で初期表示のシーンからテーブルビューのシーンへ
また初期表示シーンへ戻って、と繰り返し計測した。

#AssetBundle
テーブルビューのシーンをAssetBundle化し、また画像リソースを共通リソースと言語別リソースの
計3つのAssetBundleファイルを作成した。

![image](https://qiita-image-store.s3.amazonaws.com/0/36154/9cf5ad21-75c9-832f-2b26-06e9dc49ce2b.png)

AssetBundleはあえて英語リソースを読むように変更。
上記のように日本語リソースのサイズで設定されているので
読み込み後はSetNativeSize()をコールすればいいところだけど、今回はやっていない。

依存関係の解決処理は割愛して直接AssetBundleファイルを読み込んでいる。


#Resources
ResourcesフォルダにGUIで使用するSpriteを参照しているScribtableObjectや
Prefabを用意した。

![image](https://qiita-image-store.s3.amazonaws.com/0/36154/5670de62-0b3b-84e3-ae62-602fbf416991.png)

GUIにSpriteを設定しているとシーンロード時に読み込まれてしまうので
Spriteは未設定の状態にした。

![image](https://qiita-image-store.s3.amazonaws.com/0/36154/43c15115-fea6-07ff-463f-054ea23c3af4.png)

この状態からMonobehaviour.Start()時に各画像を設定。

#パッケージ

パッケージサイズ[byte]

| Original | AssetBundle | Resources |
|--:|--:|--:|
| 16,086,036 | 18,713,710 | 16,088,457 |
| 1.00 | 1.16 | 1.00 |

アセットバンドルはLZ4で圧縮。
読み込み時に効率がよくなるということで。
そのためかサイズが大きくなったのかもしれない。


#個人的な比較

Resources
シーンに紐づいたデータを自動でロードしてしまうため
初期設定にスプライトを設定できない。
エディタで確認できない。

ロードする処理を自分で実装しないといけない。
参照データ用のScriptableObjcet等の実装も。

AssetBundle
シーン全体をAssetBundle化することでエディタ上で確認しながら実装できる。

画面更新した後にビルドし忘れる。
ヒューマンエラー入りやすい。

IL2CPPのストリップ対応で5.5から新しいビルド方法があるので
カスタムビルドは必須になりそう。

だいたいはいい感じなんだけどメモリ使用量2倍だけは解せない。


#感想
cocos2dxで作ったアプリの同じ画像ファイルを使用して同じ画面をつくってみたんですが
Unityってなんでこんな遅いんですかね？？？
まずそれで驚きました。
cocos2dxではヌルヌルで動くのにね。

不明なのはAssetBundle使用時のメモリ利用量の多さ。
約2倍になってるですが、あれはなぜ！？

シーンの表示まで遅いので遅延読み込みを実行するなどの処理が必要そうですね。