前回の続き
tsubakit1.hateblo.jp
先日AssetBundleのキャッシュは150日しか維持出来ない事を書いた所、何やら反応があったので少し補足しておこうと思う。
ちなみにキャッシュが消される原因はコレ。
Caching.expirationDelayCachingクラスを見れば判る通り、実はキャッシュが消される条件は他にもある。
http://docs.unity3d.com/Documentation/ScriptReference/Caching-expirationDelay.html
例えばmaximumAvailableDiskSpaceとか、ClearCacheとか。
それを踏まえて、AssetBundleをどう管理するべきか考えてみた。
AssetBundleを構築するパターン
とりあえずAssetBundleを構築するパターンを幾つかリストアップし、表に纏めてみた。
・大量のアセットを単体AssetBundleに固める
・単体アセットを含むAssetBundleを大量に作る
・大量のアセットを単体AssetBundleに含める(無圧縮)
・単体アセットを含むAssetBundleを大量に作る(無圧縮)
・圧縮済みAssetBundleをLoadfromCacheOrDwonalodでキャッシュ
個別と大量の違いは、個別にまとめるか一括でまとめるかの違い。個別でまとめる場合、差分ロードを使わないとマテリアルの重複部も含めてしまうため、ファイルサイズが大きくなる傾向にある。
単純にパフォーマンスで言えばキャッシュしたものが一番良いが、管理が難しいのと150日で消される制限があり、単純にDL→キャッシュの運用では難しい事が分かる。
圧縮AssetBundleはファイルサイズ的には非常に有効だが、いかんせんメモリ消費が激しすぎる上にロードが遅い。逆に無圧縮AssetBundleはパフォーマンス的には優れているが、ファイルサイズが大きい。
ちなみにAssetBundleを大量にキャッシュする場合、Caching.readyがtrueになるまで待たないとキャッシュの読み込みが失敗することがある。その場合、メモリをWWWと同量喰うのでLoadFromCacheOrDownload使ってるのにメモリ消費が多い場合は気をつけるべし。
Caching.ready
http://docs.unity3d.com/Documentation/ScriptReference/Caching-ready.html
どの方法で運用すべきか
これは状況によりけりで、状況によって使い分けるべき。
ここに書くのは自分がとっさに聞いた時に選択する一例。
1.読み終わったらすぐ捨てるようなデータの類
例えばjsonをAssetBundleで入手する場合。
AssetBundleをキャッシュしたいところだが、古いキャッシュを削除しない特性からキャッシュは正直おすすめできない(アプリサイズがドンドン増える)。
なので圧縮(個別)のAssetBundleで対象のjsonのみを取得しassetbundleを即破棄する。これならば瞬間メモリ消費量も大したことはなくて済む。
(AssetBundleでデータを渡すならjson止めてScriptableObjectでやれし。
サーバーからデータを取得するならmessagepack使えし)
単純に一括読みするよりロード時間がかかるので、数が多いようなら2番を採用するかAssetBundleを使わないオススメ。
2.UIのような常にアクセスするリソースの類
無圧縮のAssetBundleをzip等で圧縮してからダウンロードし、ローカルにて展開する。これならダウンロード時にアホみたいにネットワーク帯域を取られずに済む。ただし大きなファイルは解凍するのに絶望的なまでに時間が掛かる。
また全無圧縮データが残るのでファイルサイズ的に肥大化しやすい。
なおパフォーマンス的には良い感じで運用出来る。ファイルの管理も手前で出来る。
ちなみに単純にSystem.IO.Compressionは使えない。ここらへんはUniteで紹介した所なので説明はと対策は省略する。
…正直、常にアクセスするならシーンに含めたほうが良くねって思うのは秘密。
3.カードや装備のようなロードに偏りがあるリソースの類
ローカルに保存した圧縮AssetBundleをLoadFromCacheOrDownloadでキャッシュする。これならばキャッシュ後は高速で読めるし消費メモリも少なくて済む。(ただし、普段見ていないカードを見直す場合、ロードが挟まる)
この場合、圧縮前と圧縮後の両方が共存するためファイルサイズが大きくなるように思えるが、maximumAvailableDiskSpaceを小さめ(大体1プレイに必要なリソースサイズ×3程度)に設定しておけば総合ファイルサイズもそれ程大きくはならない。
またキャッシュを使うので、共通マテリアル等は PushAssetDependencies や PopAssetDependencies で固めておくとファイルサイズとメモリ消費削減を期待出来る。
これを使うならば、いっその事expirationDelay(削除までの日)を5日とかにしても良いかもしれない。
異論は認める。むしろ募集中。
(DLCキットでこの辺りを楽に管理できるようにしとくか。)