のにっき

UnityにおけるSingleton管理基板の提案

概要

Unityでシーン遷移などに依存せず、アプリ全体で共有したいオブジェクトがある場合、
Singletonパターンを利用する方は多いのではないかと思います。

今回は、よくあるSingletonパターンの実装例に対する個人的な問題点と、
それらを改善するために実装した Singleton管理基盤 の提案を行います。

よくあるパターン

実装例

以下のように、Singleton用の抽象クラスを継承させることで
Singletonを生成するパターンはよく見かける実装だと思います。

using UnityEngine;
public class SingletonMonoBehaviour <T> : MonoBehaviour where T :MonoBehaviour
{
    public static T instance;
    protected virtual void Awake()
    {
        if (instance == null)
            instance = (T)FindObjectOfType(typeof(T));
        else
            Destroy(gameObject);
    }
}

問題点(※個人の感想)

実際に上記の形で実装してみると、以下の問題が発生しました

  • Singletonクラスがいくつ存在しているのか把握しづらい
  • ライフサイクルがクラスごとにバラバラになる
    → Singletonを「初期化、リセット、解放」すべきタイミングで全て出来てるのか分からない

そのためこれらの問題は、致命的なバグにつながりやすい上に
ライフサイクルがシーン遷移などの明確なイベントに依存しない分
原因調査や修正が非常に面倒になりがちです。

Singleton管理基板の提案!

上記のデメリットを改善するため、Singletonの管理を一元化する基盤を実装してみました。

作成物

GitHubリポジトリの内容をそのままプロジェクトに追加することで、すぐに利用できる形になっています。 github.com

使い方

使い方の詳細については、GitHubリンク先のREADMEをご参照ください。
※ サンプルもリポジトリ内に含めているため、イメージしやすいと思います。

この基盤の利点

  • SingletonManagerクラス以外はSingletonにしない設計にすることで、意図せずSingletonが増えることを防止しました
  • SingletonClassBase<T>SingletonMonoBehaviourBase<T>を継承するだけでSingletonのように扱えるクラスを作成できます
  • 利用側は今まで通り {クラス名}.Instanceインスタンスを取得できます
  • Singletonクラスの登録は、細かいことを意識せず初期化するだけで自動的に行われます
  • ライフサイクルを一元管理しました。SingletonManagerクラスのメソッドを呼ぶだけで制御できます

このように、
よくあるSingleton管理のデメリットを解消することを目的とした管理基盤を実装してみました。
よろしければぜひ使ってみてください。 感想やフィードバックなどもいただけますと幸いです。