Unity开发之单例模式中的小坑

  单例模式在游戏开发中会经常用到,特别是对于那种用于管理对象的地方,采用单例模式来实现会非常方便。下面先贴上一段在Unity中实现单例模式的代码【该代码转自网上】。

using UnityEngine;
using System.Collections;

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T _instance;

    private static object _lock = new object();

    private static bool applicationIsQuitting = false;

    public static T Instance
    {
        get
        {
            if (applicationIsQuitting)
            {
                return null;
            }

            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = (T)FindObjectOfType(typeof(T));

                    if (FindObjectsOfType(typeof(T)).Length > 1)
                    {
                        return _instance;
                    }

                    if (_instance == null)
                    {
                        GameObject singleton = new GameObject();
                        _instance = singleton.AddComponent<T>();
                        singleton.name = "(singleton)" + typeof(T).ToString();

                        DontDestroyOnLoad(singleton);
                    }
                }

                return _instance;
            }
        }
    }

    public void OnDestroy()
    {
        applicationIsQuitting = true;
    }
}

  这段代码实现单例模式的方式是常规的写法,只是再Unity的应用中,代码在判断该单例未实例化时会先生成一个GameObject并附加该脚本。运行时的效果如下。
  这里写图片描述
  其中,那个(singleton)HeroManager就是利用单例模式实例化出来的。然后单例模式中的坑就在这里。就以这个英雄管理器为例,假如我有A,B两个场景,在B场景中有个预先人为创建的GameObject,并绑定了HeroManager这个脚本。如图:
  这里写图片描述
  如果在A场景中,我们有个地方事先调用了HeroManager.Instance中的一个方法,亦或是对其中的一个公有变量进行了修改,程序并不会报错,在调用HeroManager.Instance的时候单利模式的设计会自动创建一个(singleton)HeroManager出来,然后在切换到B场景的时候,其实这时候内存中就会存在两份HeroManger,这时候如果代码调用HeroManager.Instance则会出现不明确的错误,如果试图去调用其中的某个对象,很有可能会抛出“unassignedreferenceexception”,这个异常就是由于同个脚本绑定了多次对象而引起的。所以在使用单例模式的时候,如果该脚本在某些地方是手动绑定的,那么在之前部分一定不要去人为调用过,不然就会掉入这个大坑。
  

发布了47 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/it_wjw/article/details/57419955