sunagimoブログ

主にUnityに関する技術を取り上げます

【Unity】Sprite Atlasの実装(Assetbundleにも対応)

本記事で扱うUnityのバージョンは「Unity2018.3.7f1」です。



Sprite Atlasとは


docs.unity3d.com


Spriteをパッキングする機能。
複数枚の画像を一つの画像にする。



メリット


処理が軽くなります。
描画回数(Set Pass Calls)を節約できます。

こんな感じに


画像4枚をそのまま配置 → +4のSetPassCalls
画像4枚をSpriteAtlas化 → +1のSetPassCalls



作成方法


Project → Create → Sprite Atlasを選択

f:id:sunagimo_app:20190311004212p:plain



spriteAtlasファイルが作られます

f:id:sunagimo_app:20190311004246p:plain


Sprite Altasの設定

f:id:sunagimo_app:20190311004909p:plain


・Type
Masterのまま
・Include in Build
AssetBundleのときはチェックを外す 
・AllowRotation
uGUIで使用する際に表示崩れが起きるのでチェックは外す。本来はアトラスのサイズを抑えるためのもの。
・Tight Packing
uGUIで使用する際に表示崩れが起きるのでチェックは外す。本来はアトラスのサイズを抑えるためのもの。
・Padding
4のまま

パッキング

Objects for Packingという項目から、+ボタンでパッキングするSpriteを選択します。
f:id:sunagimo_app:20190311005143p:plain


選択できたらPack Previewを選択します。
f:id:sunagimo_app:20190311005238p:plain


こんな感じでパッキングされます。
f:id:sunagimo_app:20190311005300p:plain




使用方法


パッキングした元のSpriteを使用します。
f:id:sunagimo_app:20190311005829p:plain


SpriteRendererの場合はそのまま配置、
uGUIの場合はImageにつけたりと通常のSpriteと使用方法は同じです。
f:id:sunagimo_app:20190311010016p:plain


SetPass calls

【実行前】
Game ViewのStatsより確認できます。
実行前はまだAtlasの効果は出ていません。
f:id:sunagimo_app:20190311010220p:plain


【実行後】
実行するとSetPass calls減っているのがわかります。
・カメラ +1
・Atlas +1
f:id:sunagimo_app:20190311010231p:plain


uGUIだと実行前から効果がでています。
なぜか。

スクリプトから読み込む方法

もちろんScriptからも参照可能です。
ご参考に。
docs.unity3d.com




おまけ


AssetBundleでの使用方法

AssetBundleで使用する場合は、Sprite Atlasの設定のInclude in Buildのチェックを外します。

f:id:sunagimo_app:20190311010916p:plain


AssetBundleを読み込む際に、
SpriteAtlasManagerのatlasRequestedを使用します。
docs.unity3d.com


サンプルコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;

public class SpriteAtlasLoad : MonoBehaviour
{
    /// <summary>
    /// アセットバンドル名。
    /// </summary>
    [Header("アセットバンドル名")]
    [SerializeField]
    string assetBundleName = null;

    /// <summary>
    /// アセット名。
    /// </summary>
    [Header("アセット名")]
    [SerializeField]
    string assetName =null;

    [Header("イメージ")]
    [SerializeField]
    Image img = null;
    
    /// <summary>
    /// AssetBundle。
    /// </summary>
    AssetBundle assetBundle;

    void Awake()
    {
        assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + assetBundleName);
        img.enabled = false;
    }

    void OnEnable()
    {
        SpriteAtlasManager.atlasRequested += OnAtlasRequested;
    }

    void OnDisable()
    {
        SpriteAtlasManager.atlasRequested -= OnAtlasRequested;
    }

    void OnAtlasRequested(string tag, System.Action<SpriteAtlas> atlasCallback)
    {   
        var request = assetBundle.LoadAssetAsync<SpriteAtlas>(assetName);
        request.completed += (operation) => {
            atlasCallback.Invoke((SpriteAtlas)request.asset);
            img.enabled = true;
        };
    }
}




一応普通に読み込んだSpriteAtlasから参照して取れますが、
Warningが出ます。


サンプルコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;

public class SpriteAtlasLoad : MonoBehaviour
{
    /// <summary>
    /// アセットバンドル名。
    /// </summary>
    [Header("アセットバンドル名")]
    [SerializeField]
    string assetBundleName = null;

    /// <summary>
    /// アセット名。
    /// </summary>
    [Header("アセット名")]
    [SerializeField]
    string assetName =null;

    /// <summary>
    /// スプライト名。
    /// </summary>
    [Header("スプライト名。")]
    [SerializeField]
    string spName = null;

    /// <summary>
    /// イメージ。
    /// </summary>
    [Header("イメージ")]
    [SerializeField]
    Image img = null;
    
    /// <summary>
    /// AssetBundle。
    /// </summary>
    AssetBundle assetBundle;

    void Awake()
    {
        assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + assetBundleName);
    }

    void Start()
    {
        var request = assetBundle.LoadAssetAsync<SpriteAtlas>(assetName);
        request.completed += (operation) => {
            var atlas = (SpriteAtlas)request.asset;
            var atlasSp = atlas.GetSprite(spName);
            img.sprite = atlasSp;
        };
    }
}

f:id:sunagimo_app:20190311015439p:plain

atlasRequestedを使えと!



まとめ


モバイルで作る際にはどうしても必要な機能かと思います。


AssetBundleで使う際は少し癖はあるかと思いますが、
使い方さえ間違わなければとても強い味方。



使用した素材


yurudora.com


今回のプロジェクト


github.com




参考にさせていただいたサイト様


kan-kikuchi.hatenablog.com
tsubakit1.hateblo.jp
tsubakit1.hateblo.jp