2. 继承Mono的单例模式基类

前提

  1. 继承MonoBehaviour的脚本不能new
  2. 继承MonoBehaviour的脚本一定得依附在GameObject上

实现挂载式的单例模式基类

挂载式 继承Mono的单例模式基类

csharp 复制代码
/// <summary>
/// 挂载式 继承Mono的单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonMono<T>: MonoBehaviour where T:MonoBehaviour
{
    private static T instance;

    public static T Instance
    {
        get
        {
            return instance;
        }
    }


    // 子类可能要重写Awake函数,所以设置为虚函数
    protected virtual void Awake()
    {
        
        instance = this as T;
        
    }
}

TestMgr2继承单例模式的基类,然后把脚本挂在到游戏对象上去,才能在Awake赋值

csharp 复制代码
public class TestMgr2 : SingletonMono<TestMgr2>
{
    private int i;

    protected override void Awake()
    {
        // 重写Awake时候,这里不能省略
        base.Awake();

        i = 0;
    }
    public void TestLog()
    {
        print("TestMgr2" + i);
    }
    
}

测试

csharp 复制代码
public class Main : MonoBehaviour
{

    private void Start()
    {
        TestMgr2.Instance.TestLog();
    }

}

缺点

因为很容易被破坏单例模式的唯一性

1.挂载多个脚本

2.切换场景回来时,由于场景放置了挂载脚本的对象,回到该场景时 又会有一个该单例模式对象

3.还可以通过代码动态的添加多个该脚本 也会破坏唯一性

修改Awake

csharp 复制代码
/// <summary>
/// 挂载式 继承Mono的单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonMono<T>: MonoBehaviour where T:MonoBehaviour
{
    private static T instance;

    public static T Instance
    {
        get
        {
            return instance;
        }
    }


    // 子类可能要重写Awake函数,所以设置为虚函数
    protected virtual void Awake()
    {
        //已经存在一个对应的单例模式对象了 不需要在有一个了
        if(instance != null)
        {
        	// 只会移除脚本
            Destroy(this);
            return;
        }
        instance = this as T;
        //我们挂载继承该单例模式基类的脚本后 依附的对象过场景时就不会被移除了
        //就可以保证在游戏的整个生命周期中都存在 
        DontDestroyOnLoad(this.gameObject);
    }
}

实现自动挂载式的单例模式基类

创建单例模式基类SingletonAutoMono,实现动态挂载脚本

csharp 复制代码
/// <summary>
/// 自动挂载式的 继承Mono的单例模式基类
/// 推荐使用 
/// 无需手动挂载 无需动态添加 无需关心切场景带来的问题
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonAutoMono<T> : MonoBehaviour where T:MonoBehaviour
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if(instance == null)
            {
                //动态创建 动态挂载
                //在场景上创建空物体
                GameObject obj = new GameObject();
                //得到T脚本的类名 为对象改名 这样再编辑器中可以明确的看到该
                //单例模式脚本对象依附的GameObject
                obj.name = typeof(T).ToString();
                //动态挂载对应的 单例模式脚本
                instance = obj.AddComponent<T>();
                //过场景时不移除对象 保证它在整个游戏生命周期中都存在
                DontDestroyOnLoad(obj);
            }
            return instance;
        }
    }

}

Test2Mgr2继承单例模式基类

csharp 复制代码
public class Test2Mgr2 : SingletonAutoMono<Test2Mgr2>
{
    public void TestLog()
    {
        print("Test2Mgr2");
    }
}

测试

csharp 复制代码
public class Main : MonoBehaviour
{

    private void Start()
    {
        Test2Mgr2.Instance.TestLog();
    }

}

潜在的安全问题

  1. 构造函数问题:
    继承MonoBehaviour的函数,不能new,所以不用担心公共构造函数
  2. 多线程问题:
    Unity主线程中相关内容,不允许其他线程直接调用,很少有这样的需求,所以也不用太担心
  3. 重复挂载问题:
    1. 手动重复挂载
    2. 代码重复添加

需要人为干涉,定规则,或者通过代码逻辑强制处理

相关推荐
与火星的孩子对话33 分钟前
Unity进阶课程【六】Android、ios、Pad 终端设备打包局域网IP调试、USB调试、性能检测、控制台打印日志等、C#
android·unity·ios·c#·ip
future141239 分钟前
C#每日学习日记
java·学习·c#
幻世界2 小时前
【Unity智能模型系列】Unity + MediaPipe + Sentis + ArcFace模型:构建高效人脸识别比对系统
unity·游戏引擎
军训猫猫头4 小时前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net
漫游者Nova9 小时前
虚幻引擎Unreal Engine5恐怖游戏设计制作教程,从入门到精通从零开始完整项目开发实战详细讲解中英字幕
ue5·游戏引擎·虚幻·游戏开发完整教程·恐怖游戏开发
死也不注释18 小时前
【Unity 编辑器工具开发:GUILayout 与 EditorGUILayout 对比分析】
unity·编辑器·游戏引擎
葬歌倾城20 小时前
JSON的缩进格式方式和紧凑格式方式
c#·json
Eiceblue1 天前
使用 C# 发送电子邮件(支持普通文本、HTML 和附件)
开发语言·c#·html·visual studio
小小小小王王王1 天前
hello判断
开发语言·c#
金增辉1 天前
基于C#的OPCServer应用开发,引用WtOPCSvr.dll
c#