(:3[kanのメモ帳]

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

Spriteをパックする新しい仕組み、SpriteAtlasを使ってみた【Unity】


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

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


はじめに

Unity 2017から新たにSpriteAtlasなるものが追加されました。



今までもSpriteをパックする(一つの画像にする)機能としてSpritePackerがありましたが、

ちょっと使ってみた感じ、SpriteAtlasの方がかなり良さげです。


SpritePackerと違い、SpriteAtlasというファイルが実際に出来るので分かりやすく、

何よりResources内でも使える(SpritePackerは使えない)というのが一番の利点でしょうか。


なお、そもそもSpriteをパックする(一つの画像にする)利点は、単純に言えば処理が軽くなる事です。

以下の画像はパックしたものとしてないものの比較で、

パック後はSetPass calls(描画回数)が減っているのが分かると思います。


f:id:kan_kikuchi:20170715064554j:plain
f:id:kan_kikuchi:20170715064605j:plain


という事で今回は、SpriteAtlasを使ってみた系の記事です。


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





SpriteAtlasの作成

まず、Create - Sprite AtlasからSpriteAtlasのファイルを作成します。


f:id:kan_kikuchi:20170713070340j:plain
f:id:kan_kikuchi:20170713070347j:plain


あとは生成したSpriteAtlasのObjects for PackingにパックしたいSpriteを指定するだけ。


f:id:kan_kikuchi:20170713071448j:plain


Spriteの指定はフォルダ単位でも可能ですし、

Pack Previewを押すとパック結果を見ることも出来ます。


f:id:kan_kikuchi:20170713071538j:plain


ただし、パックしたい画像はあらかじめTextureTypeをSpriteにする必要があります。


f:id:kan_kikuchi:20170715073521j:plain


なお、Resources内にSpriteAtlasと元の画像の両方を入れてしまうと、


f:id:kan_kikuchi:20170715070124j:plain



画像が重複して追加され、容量が増えるみたいなので、SpriteAtlasだけをResourcesにいれましょう。


f:id:kan_kikuchi:20170715070519j:plain


SpriteAtlasの設定

次にSpriteAtlasの設定項目についてです。


f:id:kan_kikuchi:20170715071503j:plain


Type

Typeは基本的にMasterで問題ありません。


もう一つのType、Variantは異なる解像度に対応する時用で、

他のSpriteAtlas(Master)を元にScaleを指定して複製する感じで使います。


f:id:kan_kikuchi:20170714071152j:plain


Include in Build

常にビルドに含めるかどうかを設定する項目で、

基本的に有効で問題ありません。


Asset Bundleを介してSpriteAtlasを使う場合には無効にした方が良いようです。


Sprite Atlas About "Include in Build" behaviour


Allow Rotation

パックする際に回転を許容するかどうかの設定で、

基本的に有効で問題ありません。


なお、Atlas内で回転するだけなので、取り出して使う時は元の状態で使えます。


Tight Packing

パックする際に詰め込むかどうかの設定で、

基本的に有効で問題ありません。


なお、Atlas内では各画像が重なっているように見えますが、取り出して使う時は元の状態で使えます。


Read/Write Enabled

Textureの情報の読み書きができるかどうかの設定で、

基本的に無効で問題ありません。


Textureをプログラムから操作したい時は有効にする必要がありますが、

使用メモリが倍になるので注意が必要です。





Generate Mip Maps

画像が遠くにある時に表示する、小さい画像(Mip Maps)を生成するかどうかの設定で、

基本的に無効で問題ありません。


有効にすると遠くのモノの解像度を下げる事で、負荷を下げる事が出来ますが、

容量が増えるので注意が必要です。


Filter Mode

フィルタの設定で、基本的にPointですが、

拡大した時に補完して欲しい場合はBilinear OR Trilinearを使います。





Max Texture Size

パックした画像の最大サイズを設定します。

基本値は2048ぐらいで、あまり大きすぎると表示できないスマホもあるので注意が必要です。


もし、この設定値より大きくなりそうな場合は自動で分割してくれますが、

違う画像にまとめられたモノを表示した場合はSetPass calls(負荷)は減りません。


なお、分割された各画像の確認は右上のプルダウンから行う事ができます。


f:id:kan_kikuchi:20170715073104j:plain


Compression

圧縮形式の設定です。

基本はNoneで良いですが、容量を減らしたい時は適宜他の設定にします。

もちろん圧縮するほど画像は劣化するので、注意が必要です。


SpriteAtlasの取得

では生成&設定を終えたSpriteAtlasを実際に使ってみましょう。

SpriteAtlasは他のファイル同様、Resources.Loadで取得でき、

SpriteAtlasのGetSprite(画像の名前)を使う事でSpriteを取得出来ます。

/*SpriteAtlasを使うには using UnityEngine.U2D; が必要*/

//Resources直下にあるWeaponAtlasという名前のSpriteAtlasを取得
SpriteAtlas weaponAtlas = Resources.Load<SpriteAtlas>("WeaponAtlas");

//WeaponAtlasに含まれているaxe2というSpriteを取得
Sprite sprite = weaponAtlas.GetSprite("axe2");


もちろん、Inspectorから設定して使う事も可能です。

//Inspectorから設定して使う
[SerializeField]
private SpriteAtlas _weaponAtlas = null;

f:id:kan_kikuchi:20170717083901j:plain


また、GetSpritesでSpriteAtlasに含まれる全Spriteの取得が可能です。

ただし、返り値として取得するわけではなく、引数にSpriteの配列を渡し

その中に全Spriteが追加される感じです。

//WeaponAtlasに含まれるSpriteの数を取得
int spriteCount = _weaponAtlas.spriteCount;

//spriteの空の配列を作成、サイズはAtlasに含まれるSpriteの数
Sprite[] spriteArray = new Sprite[spriteCount];

//spriteArrayに全Spriteを設定
_weaponAtlas.GetSprites(spriteArray);


なお、SpriteAtlasのGetSprite(s)で取得したSpriteの名前には、(Clone)が付きます。


f:id:kan_kikuchi:20170717082322j:plain


おわりに

SpritePackerのResources内では使えないという致命的な問題が無くなり、

だいぶ使い易くなったSpriteAtlasですが、

GetSpriteで取得する際に文字列で指定する必要があったり、全Spriteの取得が面倒だったり、

いくつか改善の余地がありそうです。


ということで次回は、このあたりを良い感じにする記事を予定しております!


-----------------------------追記

書きました!





参考