名古屋でアプリ・VR開発を行っています
ワクワクできるゲームをガンガン開発リリース中!

Unityのスプライトアトラスから画像を取得する時の注意点!

みなさん、こんにちは!SAT-BOXのツバメです。

今回はUnityでスプライトアトラスから画像を取得していた際に発生した事例についてご紹介しようと思います。頻繁にスプライトアトラスから画像を取得する方は要注意です!

1.ゲームが徐々に重くなっていく…

開発中のゲームをプレイ中にある現象が発生しました。時間経過と共にゲームが重くなっていくという現象です。何かしらのゴミがゲーム中に大量に残っているだけかと思いましたが、探してもどこにも無く・・・。プロファイラーを見ていたらあるものが大量に増えていました。それは・・・。
f:id:sat-box:20210427113458p:plain
レンダリング時のバッファでした!これがどんどん増えていきます。その原因がスプライトアトラスから取得した画像でした!
https://i.gyazo.com/4a0a652d40e82fb98f86d2eebf0ab22f.gif
GIF動画ではUpdateで丸画像にスプライトアトラスから同じ丸画像を取得して渡しているだけです。バッファが増えているのが分かると思います。

2.増え続ける理由

スプライトアトラスから画像を取得した場合は画像は複製される仕様になっています。そのため、同じ画像でも常に複製し続け、使っていない画像でもデータは一時保存されたままなので、バッファが増え続けてしまいます。もちろん、バッファを解放すれば問題はありませんが、根本的な問題は解決しません。

3.解決方法

事前に画像をスプライトアトラスから取得して保存しておき、保存した画像を使い回すことで解決します。今回はDictionaryを使用して画像データを使いまわそうと思います。以下コードになります。

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

public class Test : MonoBehaviour
{
    [SerializeField, Header("画像を反映するSpriteRenderer")]
    private SpriteRenderer spriteRer;

    [SerializeField, Header("スプライトアトラス")]
    private SpriteAtlas atlas;

    /// <summary>
    /// 画像データの保持用Dictionary
    /// </summary>
    Dictionary<string, Sprite> dicSpData = new Dictionary<string, Sprite>();

    /// <summary>
    /// 取得する画像名
    /// </summary>
    string spName = "circle";

    void Update()
    {
        Sprite sp;

        // Dictionaryに指定の画像名で保存されていない場合
        if (!dicSpData.ContainsKey(spName))
        {
            // スプライトアトラスから画像を取得
            sp = atlas.GetSprite(spName);

            // Dictionaryに画像名と画像データを追加
            dicSpData.Add(spName, sp);
        }
        else
        {
            // Dictionaryから指定の画像を取得
            dicSpData.TryGetValue(spName, out sp);
        }

        spriteRer.sprite = sp;
    }
}

 
このようにしてしまえば、画像データの複製は抑えることができ、バッファの増加も防ぐことができます。

今回のケースはすぐに分かるようなものではなく、時間経過で発生するので、なかなか気づけないかと思います。スプライトアトラスから画像を取得しようとしている方は注意した方が良いかもしれないです。

以上、ツバメでした!