首页 > 其他分享 >Unity中常用的三种单例模式基类

Unity中常用的三种单例模式基类

时间:2024-09-19 14:52:55浏览次数:11  
标签:instance Unity static 单例 基类 null public

提到框架,大家可能会觉得很复杂,我也是有同感

但好在,也不是所有的框架都需要我们掌握的

但这期提到单例模式却是大家一定要掌握!!!

因为它真的非常重要!!!


这里我整理了三种开发中常用的单例模式基类,希望大家看完后能多敲几遍,把它变成自己的知识

(如果想直接拿到代码的话可以在我上传的资源中搜索单例就可以免费下载)

注:后面的mono指的就是Unity中的MonoBehaviour类

第一种,不继承mono的单例基类(这种自然就无法挂载到GameObject上了)

最大的缺点就是它的构造函数还可以在外部调用,会破坏唯一性

但这一点也可以很好的规避,那就是不去调用它的构造函数(只要懂得单例模式的程序员都不会犯这个问题)

另一种解决方法就是使用反射相关的知识,请大家看第二段代码

/// <summary>
/// 单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class BaseManager<T>where T: class,new ()
{
    private static T instance;
    //通过属性获取,任选其一
    public static T Instance
    {
        get
        {
            if (instance == null)
                instance = new T();
            return instance;
        }
    }
    
    //通过属性获取,任选其一
    public static T GetInstance()
    {
        if (instance == null)
            instance = new T();
        return instance;
    }
}

这种写法就可以规避上面提到的问题,但需要注意的是继承此类的类,必须要有一个自己的私有的无参构造函数 (后面的这段代码作为参考)

using System;
using System.Reflection;
using UnityEngine;

/// <summary>
/// 单例模式基类
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BaseMgr<T>where T: class
{
    //继承BaseMgr的子类需要自己创建一个私有的无参构造
    private static T instance;    
    //通过属性获取
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                //利用反射得到私有的无参构造函数 来用于对象的实例化
                Type type = typeof(T);
                ConstructorInfo info = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
                                                           null,
                                                           Type.EmptyTypes,
                                                           null);
                if (info != null)
                    instance = info.Invoke(null) as T;
                else
                    Debug.LogError("没有找到对应的无参构造函数");
            }
            return instance;               
        }
    }    
}
public class TestMgr : BaseMgr<TestMgr>
{    
    //不继承mono的单例还要声明一个私有的无参构造,为了不让外面调用
    private TestMgr() { }
    public void TestLog()
    {
        Debug.Log("测试");
    }
}

第二种,继承mono但需要自己进行挂载的单例基类

创建完脚本后还需要自己挂载到需要的GameObject上

using UnityEngine;
 
/// <summary>
/// 手动挂载的继承mono的泛型单例
/// </summary>
public class SingletonMono<T> : MonoBehaviour where T: SingletonMono<T>
{
    private static T instance; // 唯一实例
 
    // 向外提供
    public static T Instance 
    {
        get { return instance; }
    }    
 
    protected virtual void Awake()
    {
        // 要是不为空,表示已经存在一个单例 销毁
        if(instance != null)
        {
            Destroy(this.gameObject);
        }
        else
        {
            // 强转单例
            instance = (T)this;
        }
    }    
}

第三种,继承mono但可以自动进行挂载的单例基类

using UnityEngine;

/// <summary>
/// 自动挂载的单例模式基类
/// </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脚本类名 为对象改名 这样编辑器中观看更明确
                obj.name=typeof(T).Name;
                //动态添加脚本 记得为instance赋值
                instance=obj.AddComponent<T>();
                //过场景不移除 保证它在整个游戏生命周期中都存在
                DontDestroyOnLoad(obj);
            }
            return instance;
        }
    }
}

标签:instance,Unity,static,单例,基类,null,public
From: https://blog.csdn.net/Blueberry124/article/details/142360043

相关文章

  • Unity坐标系求向量的模长
    Unity坐标系求向量的模长publicfloat sqrMagnitude;返回该向量的平方长度。(只读)向量 v 的大小以Mathf.Sqrt(Vector3.Dot(v,v))方式进行计算。但是,Sqrt计算相当复杂,执行时间比普通算术运算要长。计算平方数代替使用 magnitude 属性要快得多-计算基本相同,只是......
  • Unity自定义图片数字TextMeshPro
    本文转载自https://www.cnblogs.com/sailJs/p/181689221、首先要有一张包含了图片字的图集,每个图片字一个Spirte 2、然后右键-> 创建创建好的TMP_SpriteAsset 3、编辑SpriteCharacterTable调整顺序,将index和图片数字对上修改下Unicode值(默认都是0xFFFE),比如9的Un......
  • Unity使用TextMeshPro实现聊天图文混排
    本文来自:https://developer.aliyun.com/article/10666231.文字自适应问题。2.图文混排问题。UI界面1.创建滑动列表首先创建一个可以上下滑动的列表,命名为chat_scroll2.创建聊天预制因为聊天是两人以上的,自己的聊天显示在右侧,别人的聊天消息显示在左侧。因此需要制作两个聊天......
  • Unity UI控件用法汇总
    利用LoopListView实现Banner循环列表,且默认中间节点为默认节点:  1.给ScrollRect节点添加LoopListView组件,并勾选ItemSnapEnable为true。  2.通过LoopListView.InitListView初始化时,totalCount需要传-1.  3.OnGetItemByIndex的回调参数index以(Int32.MinValue,Int32.MaxVa......
  • Day23笔记-Day21和Day22作业讲解&单例类
    Day22作业讲解'''学生类Student:属性:学号,姓名,年龄,性别,成绩​班级类Grade:属性:班级名称,班级中的学生【使用列表存储学生】​方法:1.查看该班级中的所有学生的信息2.查看指定学号的学生信息3.查看......
  • 手把手教你写一个Unity对象池
    对象池,我在最初学习时觉得这一定是个非常复杂的东西,但其实从现在看过去,对象池其实非常简单。首先对象池也叫做缓存池,是常见的一种优化内存的手段(划重点,常用,一定要学会哦)再来看,对象池主要用于面对以下问题:1.对象的频繁创建频繁的实例化对象会带来一定的性能开销2.对象的频......
  • 【Unity精品源码】打造甜蜜的三消游戏:Candy Match 3 Kit
    最近总熬夜,肝不好,大家都叫我小心肝。......
  • 在Unity UI中实现UILineRenderer组件绘制线条
    背景介绍        在Unity的UI系统中,绘制线条并不像在3D世界中那样直观(使用Unity自带的LineRender组件在UI中连线并不方便,它在三维中更合适)。没有内置的工具来处理这种需求。如果你希望在UI元素之间绘制连接线(例如在UI上连接不同的图标或控件),需要自己编写逻辑。 ......
  • Unity3D下如何播放RTSP流?
    技术背景在Unity3D中直接播放RTSP(RealTimeStreamingProtocol)流并不直接支持,因为Unity的内置多媒体组件(如AudioSource和VideoPlayer)主要设计用于处理本地文件或HTTP流,而不直接支持RTSP。所以,你可以通过一些间接的方法来实现RTSP流的播放,或者通过比较成熟的第三方插件来播。可选方......
  • Unity3D下如何播放RTSP流?
    技术背景在Unity3D中直接播放RTSP(RealTimeStreamingProtocol)流并不直接支持,因为Unity的内置多媒体组件(如AudioSource和VideoPlayer)主要设计用于处理本地文件或HTTP流,而不直接支持RTSP。所以,你可以通过一些间接的方法来实现RTSP流的播放,或者通过比较成熟的第三方插件来播。......