2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ランタイムなマネージャクラスでの運用すゝめ

Last updated at Posted at 2019-12-12

経緯

Unity上でシングルトンなクラスはあまり多く作ると管理がいろいろ面倒になったりする
シーンに依存するマネージャ( そのシーンでだけ利用するマネージャ )にシングルトンを利用するのも若干非効率なためランタイムに生成し、該当シーンが終了したら削除されるようなマネージャがあると勝手が良いかも???
あくまで一つの案として...

スクリプト

まずはゲームマネージャが管理できるランタイムマネージャのベースクラスの作成

using UnityEngine;

namespace sample
{
    /// <summary>
    /// シングルトンではない通常のマネージャクラスを作成するためのベースクラス.
    /// シーンに依存するマネージャやほかのシーンでは使う場面が全くないものなどに使う.
    /// Awakeで必ずGameManagerに登録すること.
    /// </summary>
    public class RuntimeManagerBase : MonoBehaviour
    {
        public override string ToString()
        {
            return GetType().ToString();
        }
    }
}

GameManagerクラスではDictionaryで管理するためキー値用のstringを取得するためのToString()メソッドをオーバーライドする

続いてGameManagerクラス

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


namespace sample
{
    /// <summary>
    /// ゲームマネージャ.
    /// </summary>
    public class GameManager : SingletonMonoBehaviour<GameManager>
    {


        Dictionary<string, RuntimeManagerBase> managerDic;


        protected override void Awake()
        {
            base.Awake();
            managerDic = new Dictionary<string, RuntimeManagerBase>();
            DontDestroyOnLoad(this);
            SceneManager.activeSceneChanged += ActiveSceneChangeListener;
            SceneManager.sceneUnloaded += SceneUnLoadedListener;
        }

        
        /// <summary>
        /// 登録済みのランタイムマネージャを取得.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetRuntimeManager<T>() where T : class
        {
            if (!Instance.managerDic.ContainsKey(typeof(T).ToString())) return null;
            return Instance.managerDic[typeof(T).ToString()] as T;
        }


        /// <summary>
        /// ランタイムマネージャを登録.
        /// </summary>
        /// <param name="manager"></param>
        public static void RegisterRuntimeManager(
            RuntimeManagerBase manager)
        {
            string typeString = manager.ToString();
            if (Instance.managerDic.ContainsKey(typeString)) return;
            Instance.managerDic.Add(typeString, manager);
        }


        // シーンが破棄された故タイミングのリスナ.
        static void SceneUnLoadedListener(
            Scene scene)
        {
            // ランタイムマネージャはこのタイミングで破棄.
            Instance.managerDic?.Clear();
        }


        // シーン変更検知,Unityの仕様上beforeには何も入っていない,afterにロードされたシーンがある.
        static void ActiveSceneChangeListener(
            Scene before,
            Scene after)
        {
        }
           
        
    }
}

↑スクリプト中にある SingletonMonoBehaviour に関しては UnityでMonoBehaviourのシングルトンを参考に作成しています

今回の実装では簡単にランタイムマネージャの登録処理,ランタイムマネージャの取得処理,シーンの変更時にランタイムマネージャの破棄処理を行っている
ランタイムマネージャの破棄用メソッドを用意していないのはどのみちシーン遷移時に破棄されるため

後はお好みでゲームに必要な処理を追加していけばよいと思う
難点としてはGameManagerに依存しがちになってしまうのでGameManagerが神クラス化してしまわないかなど...
あるいはManagerProviderという名前にしてGameManagerとは別のクラスでやればGameManagerがやるべき仕事と分離できるかも?

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?