読者です 読者をやめる 読者になる 読者になる

全てのシーンに存在し、一つしか存在してはいけないマネージャー的存在の実装

kan-kikuchi.hatenablog.com

この記事を読んで、最近読んだFruitsNinjaをCloneしたアセットのことを思い出したので記事にします。

https://www.assetstore.unity3d.com/jp/#!/content/65879

ところで、このアセット、凄いです!画像変えるだけで、vegetable ninjaでもmeat ninjaでも何でも作れます!
こんなん無料で出すなんて太っ腹すぎる!しかもコードに書かれたコメントがめちゃくちゃ丁寧!
オススメです!

本題に戻ります。
上記の記事で問題として挙げられていることを列挙すると

  1. 全てのシーンに存在して欲しいが、いちいち全てのシーンに配置するのは面倒だし、シーンが変わる度にマネージャーが新しくなるので、シーンを跨いでの処理ができなくなる。
  2. かといってDontDestroyOnLoadを使ってマネージャーが消えないようにすると、シーンを移動した時にマネージャーが重複してしまう。
  3. かといって最初のシーンだけに設置すると、他のシーン単体でテストが出来ない。

ということです。なので、

  1. 全てのシーンに存在し、
  2. 重複せず
  3. シーン単体でのテストができる

ことが重要になります。

FruitsNinjaCloneのスクリプトにあるSingletonは、かなり上記の条件を満たしています。

コードを一部簡略化して載せると、

public class Singleton<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)
                {
                    GameObject singleton = new GameObject();
                    _instance = singleton.AddComponent<T>();
                    singleton.name = "(singleton) " + typeof(T).ToString();

                    DontDestroyOnLoad(singleton);
                }
            }

            return _instance;
        }
    }
}

というような形になっています。

キモは、instanceが無かったらGameObjectを生成して、AddComponentしているところです。

これで、Instanceにアクセスが発生した瞬間にオブジェクトが生成されます。

問題点としては、Instanceへのアクセスが無ければオブジェクトが生成されずEditor上にもオブジェクトが現れないことですが、たいてい、どっかでアクセスがあるし、明示的にInstanceへのアクセスをしてやれば無理やり作ることもできるし、まあまあ良い感じなんじゃないかと思います。



1分間たまご - 激ムズ!

1分間たまご - 激ムズ!

開発元:Ken Watanabe
無料

posted with アプリーチ