はじめに
UnityにはCrunch圧縮という機能がありTextureのサイズを劇的に減らすことができます。
ビルドサイズを削減するという点では非常に有効だと思うのですがロード時間の短縮と言う点ではどうなのでしょうか?
ビルドサイズが小さくなれば当然読み込み時間は短くなるでしょうが圧縮しているため解凍する必要があります。IOの高速化により短縮できる時間と解凍にかかる時間のどちらの方が大きいのかを測定してみました。
結論から言うとCrunch圧縮した方がいいぜって話です。
環境
OS:Windows10 64bit
ビルドターゲット:Windows(スタンドアロン) LZ4圧縮は無し
Unityバージョン:2019.2.0f1
プロセッサ:Corei3-6100U
CrystalDiskMark:
測定方法
フルHDから4Kまでのテクスチャが存在しておりメモリ上には1.3GBのテクスチャが載っています。
このシーンをAssetBundleに格納し、ロードします。
以下のスクリプトでロード時間を測定します。
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using System.Collections;
public class StartTimer : MonoBehaviour
{
private void Update()
{
if (Input.GetButtonDown("Jump"))
{
StartCoroutine(Load());
}
}
IEnumerator Load()
{
File.AppendAllText(Application.streamingAssetsPath + "/result.txt", "LoadStart..." + Time.time+"\n");
var result = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/sphere");
yield return new WaitWhile(() => {
return !result.isDone;
});
var assetbundle = result.assetBundle;
File.AppendAllText(Application.streamingAssetsPath + "/result.txt", "ABLoadComplete..." + Time.time+"\n");
string sceneName = Path.GetFileNameWithoutExtension(assetbundle.GetAllScenePaths()[0]);
SceneManager.LoadScene(sceneName);
}
}
using UnityEngine;
using System.IO;
public class CompleteTimer : MonoBehaviour
{
void Start()
{
File.AppendAllText(Application.streamingAssetsPath + "/result.txt", "LoadComplete..." + Time.time+"\n");
}
}
(AssetBundleからのシーン読み込みの方法はこちらのブログを参考にさせていただきました。http://tsubakit1.hateblo.jp/entry/2016/08/23/233604)
開始時に読み込まれるシーンのGameObjectにStartTimer.csをアタッチし、CompleteTimer.csは先ほどのテクスチャいっぱいのシーンのGameObjectにアタッチしておきます。
この測定をCrunch圧縮なし/ありでそれぞれ行いロード時間を比較したいと思います。
なおCrunch圧縮のクオリティは50でやっていきます。
#結果
###Crunch圧縮無し
LoadStart...0.9617942
ABLoadComplete...32.18606
LoadComplete...32.20223
アセットバンドルサイズ : 267,533KB(267.5MB)
アセットバンドルのロードにかかった時間 : 31.2242658秒
アセットバンドルロード完了後にシーンの読み込みにかかった時間 : 0.01617秒
###Crunch圧縮あり
LoadStart...10.97006
ABLoadComplete...21.08436
LoadComplete...21.10166
アセットバンドルサイズ : 105,891KB(105.9MB)
アセットバンドルのロードにかかった時間 : 10.1143秒
アセットバンドルロード完了後にシーンの読み込みにかかった時間 : 0.0173秒
Crunch圧縮によりアセットバンドルのサイズは半分以下に、読み込み時間は3分の1ほどになりました。
シーンの読み込みにかかった時間はCrunch圧縮ありの方がほんのわずかに遅かったですが誤差レベル。人間には知覚できないでしょう。
#AssetBundle無し
それではアセットバンドルをビルドせずにシーンを直接組み込んだ場合はどうでしょうか。
環境及び計測方法は大体同じです。
###Crunch圧縮無し
LoadStart...1.388524
LoadComplete...1.41218
ビルドサイズ:652 MB
シーンのロード時間:0.023656
###Crunch圧縮あり
LoadStart...1.386678
LoadComplete...1.408058
ビルドサイズ:236 MB
シーンのロード時間:0.02138
ビルドサイズは3分の1ほどになりましたがシーンのロード時間はほぼ変わりませんでした。
またゲームの起動時間は測定方法が分からなかったので測定できませんでしたが体感には全く差は感じられませんでした。
#まとめ
Crunch圧縮をすることでビルドサイズが劇的に小さくなった上に解凍によるオーバーヘッドは全く感じられませんでした。特にアセットバンドルからのシーンロードの際にはCrunch圧縮した方が圧倒的にロードが速かったです。すべてのデータを毎度ネットワークからロードしてくるWebGLなどではさらに大きく差が開くことでしょうし、モバイルアプリにおいてもダウンロードサイズを抑えるための有効な手段になるはずです。
環境によっても変わってくるでしょうが基本的にはCrunch圧縮はしていく方向でいいのではないでしょうか。
ただしテクスチャの各辺の長さが4の倍数でなければ圧縮できませんし、Crunchは不可逆圧縮なので画像が劣化する可能性がある点は注意が必要です。