(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

1Asset = 1AssetBundleにした場合と、まとめた場合でのロード時間比較【Unity】【AssetBundle】


このエントリーをはてなブックマークに追加


この記事でのバージョン
Unity 2017.2.0f3


はじめに

AssetBundleを使う上での検討事項として、

どれぐらいの規模でAssetをまとめればいいのかというものがあります。


用途や状況によって分け方は変わってくるとは思いますが、

今回はローカルからのロード時間に着目し、比較を行ってみました。


なお、記事中では以下のアセットを使っております。





比較

比較の対象はサイズが約1000×1000の画像100枚です。


f:id:kan_kikuchi:20171018072855j:plain


これを1Asset = 1AssetBundleにした場合と、1つののAssetBundleにまとめた場合で

全AssetBundleのロード時間と、

ロードした全AssetBundleから全Spriteをロードする時間を比較しました。


なお、処理時間の計測には以前紹介したProcessTimerを使いました。



比較に用いたコードは以下の通りです。

//処理時間の合計
private float _assetBundleTotalTime = 0, _spriteTotalTime = 0;

private void Start () {
  //指定したディレクトリに入っている全ファイルを取得
  string[] filePathArray = Directory.GetFiles ("Assets/AssetBundle", "*", SearchOption.AllDirectories);

  //取得したファイルの中からAssetBundleのパスだけリストに追加する
  List<string> assetBundlePathList = new List<string>();
  foreach (string filePath in filePathArray) {
    if(!string.IsNullOrEmpty(Path.GetExtension(filePath))){
      continue;
    }
    else if(Path.GetFileName(filePath) == "AssetBundle"){
      continue;
    }
    assetBundlePathList.Add (filePath);
  }

  //100回計測を行い平均をログで表示
  int measurementNum = 100;
  for (int i = 0; i < measurementNum; i++) {
    Measure(assetBundlePathList);
  }

  Debug.Log("AssetBundle取得時間の平均 : "          + (_assetBundleTotalTime                      / measurementNum));
  Debug.Log("Sprite取得時間の平均 : "               + (_spriteTotalTime                           / measurementNum));
  Debug.Log("AssetBundle + Sprite取得時間の平均 : " + ((_assetBundleTotalTime + _spriteTotalTime) / measurementNum));
}

//計測処理
private void Measure(List<string> assetBundlePathList){
  //AssetBundle取得し、時間を計測
  List<AssetBundle> assetBundleList = new List<AssetBundle>();
  ProcessTimer.Restart();

  foreach (string assetBundlePath in assetBundlePathList) {
    assetBundleList.Add(AssetBundle.LoadFromFile(assetBundlePath));
  }

  _assetBundleTotalTime += ProcessTimer.Stop();

  //AssetBundleから全Spriteを取得し、時間を計測
  List<Sprite> spriteList = new List<Sprite>();
  ProcessTimer.Restart();

  foreach (AssetBundle assetBundle in assetBundleList) {
    spriteList.AddRange(assetBundle.LoadAllAssets<Sprite>().ToList());
  }

  _spriteTotalTime += ProcessTimer.Stop();

  //アセットバンドルをアンロード(処理時間は計測しない)
  foreach (AssetBundle assetBundle in assetBundleList) {
    assetBundle.Unload(unloadAllLoadedObjects : false);
  }
}

f:id:kan_kikuchi:20171020102605j:plain


そして、計測結果は以下の通りです。

ついでにAssetBundleの容量も記載してあります。

AssetBundleの数 AssetBundleのロード[秒] Spriteのロード[秒] 計[秒] 容量[MB]
1 4.4746 0.0172 4.4917 56.8
100 5.0175 0.0476 5.0651 57.3


やはりAssetBundleのロード時間も、Spriteのロード時間も小分けにした方が長くなりました。

また、小分けにすると容量も増えるようです。


ちなみにResources.LoadAllでは全Spriteをロードするのに0.18秒ぐらいだったので、

当たり前ですが、AssetBundleを使う必要がなければ使わないに越したことはありません。


おわりに

今回の結果はロード時間の点でも、容量の点でも一つのAssetBundleにまとめた方が有利でしたが、

あくまでローカルから全AssetBundle&全Spriteを一度にロードする場合の話で、

個別にロードする場合やサーバからダウンロードしてくる場合は話が変わってくるので注意が必要です。