Unityやってるワン

Unityで勉強したことを備忘録として記事にしていきます

継承することでシングルトンパターンで実装できるクラスを作ってみた

前回シングルトンパターンで管理系のクラスを作成する記事を書きました。
シングルトンでマネージャーっぽいクラスを作ってみた - Unityやってるワン


でも、シングルトンのパターンで実装するたびにstaticでインスタンスを保持する処理を用意するのはちょっと面倒です。なので継承することでシングルトンクラスとして実装することができるクラスを作ってみました。このクラスを継承すれば、シングルトンのパターンを毎回用意する必要がなくなりそうです。


SingletonClass.cs

using UnityEngine;

/// <summary>
/// シングルトンクラス
/// </summary>
public class SingletonClass<T> : MonoBehaviour
{
    /// <summary>インスタンス</summary>
    private static T m_instance;



    /// <summary>
    /// インスタンス取得
    /// </summary>
    public static T Singleton
    {
        get
        {
            if (m_instance == null)
            {
                //シングルトンオブジェクト生成
                var components = new[]{ typeof( T ) };
                GameObject obj = new GameObject(typeof(T).Name, components);
                m_instance = obj.GetComponent<T>();

                //シーン遷移時に破棄させないようにする
                DontDestroyOnLoad(obj);
            }

            return m_instance;
        }
    }

    /// <summary>
    /// インスタンスの生成を無効化
    /// </summary>
    protected SingletonClass () { }
}

シングルトンパターンのクラスSingletonClass.csを作ってみました。
ジェネリックでシングルトンパターンのクラスを宣言しています。SingletonClassを継承する際に継承先のクラスを渡す形で使用します。
ジェネリックとは、決まった型持たず後から型を指定することができる方法です。
実際にSingletonClassを使う場合は以下のような感じになります。


PointManager.cs

using UnityEngine;

/// <summary>
/// 得点管理クラス
/// </summary>
public class PointManager : SingletonClass<PointManager>
{
    /// <summary>得点</summary>
    private int m_point = 0;



    /// <summary>
    /// インスタンスの生成を無効化
    /// </summary>
    private PointManager () { }

    /// <summary>
    /// ポイント加算
    /// </summary>
    /// <param name="_point">加算するポイント</param>
    public void AddCount (int _point = 1)
    {
        m_point += _point;
    }

    /// <summary>
    /// ポイント取得
    /// </summary>
    public int Count { get { return m_point; } }
}

SingletonClassクラスを継承して得点を管理するPointManager.csを作りました。
継承する際に自身を渡してジェネリッククラスに型を認知させています。
これで、シングルトンのパターンを用意する手間が省けそうですね。


PointManagerは以下のような形で利用できます。

PointManager.Singleton.AddCount();
PointManager.Singleton.AddCount(10);
Debug.Log("現在の得点:" + PointManager.Singleton.Count);

f:id:nsdeveloperman:20170708164929p:plain

シングルトンでマネージャーっぽいクラスを作ってみた

Unityで入力や音声などを管理するクラスを作成する際は、シングルトンのパターンで実装することが多いようです。
シングルトンとはインスタンスが1つしか生成されないようにする実装パターンです。
〇〇Managerみたいな管理系のクラスは複数存在することがないようにこのパターンで実装するのがいいと思います。


ManagerClass.cs

using UnityEngine;

/// <summary>
/// マネージャークラス
/// </summary>
public class ManagerClass : MonoBehaviour
{
    /// <summary>インスタンス</summary>
    private static ManagerClass m_instance;

    /// <summary>
    /// インスタンス取得
    /// </summary>
    public static ManagerClass Instance
    {
        get
        {
            if (m_instance == null)
            {
                //オブジェクト生成
                GameObject managerObject = new GameObject("ManagerClass");
                m_instance = managerObject.AddComponent<ManagerClass>();

                //シーン遷移時に破棄させないようにする
                DontDestroyOnLoad(managerObject);
            }

            return m_instance;
        }
    }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    protected ManagerClass () { }
}

実体を取得する関数を用意し、実体が生成されていなければ新たに生成するといった感じです。コンストラクタをprivateで宣言して、外部で実体を生成させないようにしています。また、GameObjectとして生成してからDontDestroyOnLoadでシーン遷移時に破棄されないようにしています。

これで入力や音声データなどを制御するManagerっぽいクラスが実装できそうですね。