AssetBundle の圧縮(1) 目的と方針
目的
AssetBundleはLZMAやLZ4で圧縮されますが、扱うデータの特性がわかっている場合はより特殊化した
圧縮が期待できるのではないかと考えました。
例えば目パチのようなアニメーションの画像データでは以下のようなアプローチがあります。
- 目だけを上書きする透過画像を生成して上に乗せる。
透過面積が多い画像であれば標準のSpritePackerや TexturePacker で効率的なAtlas化が可能です。 - 差分画像を生成する。例えば 宴 のダイシング機能。
しかし、今回は制約があり上の手法は使いません。
前提
制約は以下の通りです。
- 使う側で特別なコードは一切書きたくない。
- TextureでありSpriteではない。
- 機種依存圧縮(PVRTC, ETC)を使いたい。
- 透過なしで1パスで描画を行いたい。
PVRTC, ETC のバイト列を生成し、Unity の Texture としてロードができればよいのですが、
ちょっとわからなかったので別の方法を試します。(*1)
手法
AssetBundle をただ圧縮し、インストール時に展開するというアプローチを試してみます。
テクスチャ圧縮はGPUの機能的制約から固定長で同じサイズのテクスチャであれば、同じ座標のデータは
同じブロックに存在します。したがって、局所性が高く、同一のピクセル構成部分であれば、同一のバイナリ構成になる可能性が高いと予想されます。
(PVRTC は近辺のブロックも参照を行うので、影響範囲は少し大きめになりますが、距離に応じて影響は低くなります)
(*1) のPVRTCからテクスチャ生成ができれば、AssetBundle 内で圧縮するアプローチを取ることができるのですが、Nativeでテクスチャを生成する以外の方法があれば、誰か教えてください...。
問題点
- 圧縮前はロスレス画像でなければならない。
見た目が同じでもLossyな圧縮を行なった結果、微妙に画像データが異なると困ります。 - ストレージでの消費容量は無圧縮なので比較的大きい。
- 複数のバリエーションをロードするとGPU側のメモリ消費は多い。
- 暗号化を行えない。暗号化を先に行うと圧縮が難しい。
圧縮してから暗号化だと、ストレージでは圧縮を展開したデータになるため暗号化がかかっていない状態になります。
(2)へ続く。