Unity单例模式

单例模式通常用于生成单一管理者,例如假设游戏只能有一个玩家,那么就可以将玩家的控制器作为一个单例存在使用。或者场景控制,也可以作为一个单例来使用。

//BaseManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Singleton <T> where T:new()
{
    private static T instance;
    public static T GetInstance()
    {
        if(instance == null)
            instance = new T();
        return instance;
    }
}

public class MonoSingleton<T> : MonoBehaviour where T: MonoBehaviour
{
    protected static T instance;
    public static T GetInstance()
    {
        if(instance == null)
        {
            instance = (T)FindFirstObjectByType(typeof(T));
            if(instance == null)
            {
                GameObject singleton = new GameObject();
                instance = singleton.AddComponent<T>();
                singleton.name = typeof(T).Name;
                DontDestroyOnLoad(singleton);
            }
        }
        return instance;
    }
    void Awake()
    {
        DontDestroyOnLoad(gameObject);
        if(instance == null)
            instance = this as T;
        else
            Destroy(gameObject);
    }
}

逐步解释

public class Singleton<T> where T:new()
//使用<T>来扩大其泛用性,这样就可以直接利用这个基类建立其他单例。
//where T:new()做约束,强制要求其存在新建方法,否则后续instance = new T();无效
{
    private static T instance;
    //单例不应该被随意获取,保持为私有状态
    public static T GetInstance()
    //使用一个公有函数来对单例进行访问
    {
        if(instance == null)//单例为空
            instance = new T();//新建单例
        return instance;//返回单例,由于前面已经保证单例不为空,所以必有返回值
    }
}
//对于需要继承MonoBehaviour的单例,则会有一定的变化
public class MonoSingleton<T> : MonoBehaviour where T: MonoBehaviour
{
    protected static T instance;
    public static T GetInstance()
    {
        //检查单例是否为空
        if(instance == null)
        {
        //是空的,那就先在列表里找找,原代码是FindObjectOfType,但是因为是[Obsolete]
        //然后我不想看到一个warning搁那挂着(笑)所以就换成了FindFirstObjectByType
            instance = (T)FindFirstObjectByType(typeof(T));
        //还找不到的话就给他现做一个
            if(instance == null)
            {
                GameObject singleton = new GameObject();
                instance = singleton.AddComponent<T>();
                singleton.name = typeof(T).Name;
                DontDestroyOnLoad(singleton);
            }
        }
        return instance;
    }
    void Awake()
    {
    //单例不应该被摧毁
        DontDestroyOnLoad(gameObject);
        if(instance == null)
            instance = this as T;
   //如果存在多重单例,那就销毁其他单例
        else
            Destroy(gameObject);
    }
}
posted @ 2023-12-26 19:25  ComputerEngine  阅读(119)  评论(0编辑  收藏  举报