ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

20220329162023

Unity - シングルトンの意味と使い方 -

初めに

 ゲームを作るとき、ゲーム全体を管理するゲームマネージャーを作成します。その際、必要となってくる「シングルトン」について、まとめます。

シングルトン(singleton)とは

 シングルトンとは、実行時にそのクラスのインスタンスが1つしか作ることができないように設計することです。

 Unityで使われているC#オブジェクト指向型であり、クラスはオブジェクト(モノ)を作るための設計図のようなものです。そのため、クラスをもとに複数のオブジェクトを複製するのが通常です。しかし、ゲームマネージャーやサウンドマネージャーのように複数あっては困るオブジェクトも存在します。(例えば、サウンドマネージャーが2つあると、BGMやSEが2つ重なって流れたり、処理できずエラーを吐いたりする)そのようなオブジェクトを初めから、1つしか作ることができないように設計するのがシングルトンです。

 クラスやインスタンスオブジェクト指向型などの用語はこちらの記事で解説しております。ぜひ、ご覧ください。
fineworks-fine.hatenablog.com

シングルトンなオブジェクトの作り方

 シングルトンなオブジェクトの作り方は以下の通りです。

  • ”SingletonMonoBehavior” というクラスを作る

 ”SingletonMonoBehavior” というクラスを新たに作るために、次のスクリプトを作成しておきます。

using UnityEngine;
 
public class SingletonMonoBehaviour<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance;
 
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = (T)FindObjectOfType(typeof(T));
 
                if (instance == null)
                {
                    Debug.LogError(typeof(T) + "がシーンに存在しません。");
                }
            }
 
            return instance;
        }
    }

}

 このスクリプトはクラスTのインスタンスが存在するかどうかを判定しています。途中でgetという処理をしていますが、これはプロパティと呼ばれるものになります。

  • シングルトンにするオブジェクトにアタッチするC#スクリプトを作成する

 今回は、ゲームマネージャーを作る想定でC#スクリプトを作成するため、C#スクリプトの名前を "GameManager" にしておりますが、他の名前でも構いません。

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

public class GameManager : SingletonMonoBehaviour<GameManager>
{

    public void Awake()
    {
        if (this != Instance)
        {
            //すでにインスタンスがあれば、削除
            Destroy(gameObject);
            return;
        }

        //シーンが変わってもゲームオブジェクトが消えないようにする
        DontDestroyOnLoad(gameObject);
    }

    //以下に処理を書く
    void Start()
    {
     
    }

    void Update()
    {

    }
}

 重要な部分はクラスを "SingletonMonoBehaviour" にするところです。これで、"SingletonMonoBehaviour" のクラスを継承できます。
 Awake内では、2つ以上のインスタンスが存在していた場合、1つになるようにオブジェクトを削除するように記述しています。

(余談)ゲームマネージャーを作成するときに起こること

 C#スクリプトの名前を "GameManager" にするとアイコンが次のように変わります。



 機能は通常のC#スクリプトと変わらないようです。

  • シングルトンにしたいオブジェクトにC#スクリプトをアタッチする


 これで、オブジェクトをシングルトンにできました。複製して2つ以上にして実行してみても、ちゃんとオブジェクトが削除され、1つになっていることが分かります。また、DontDestroyOnLoad内にオブジェクトがあるため、ちゃんとシーンをまたいでもオブジェクトが削除されないようになっていることも確認できます。

シングルトンのメリット・デメリット

メリット
  • シングルトンを使って作成したオブジェクトはゲーム内に1つしか存在しないため、データなどの重複を避けられる
デメリット

 シーンをまたいでも削除されないオブジェクトが存在することは、シーン単体でのテストだけでは、バグが発見しきれないことを意味します。そのため、DontDestroyOnLoadを使うことをおすすめされないこともあります。

最後に

 シングルトンについて、まとめました。簡単にシーン間でのオブジェクトの共有ができますが、デメリットもあることが分かります。シングルトンではないデータの共有方法もあります。リンク先に紹介してあります。
note.com