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

devtools/2024/10/18 23:24:22/

前提

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

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

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


/// <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赋值


public class TestMgr2 : SingletonMono<TestMgr2>
{private int i;protected override void Awake(){// 重写Awake时候,这里不能省略base.Awake();i = 0;}public void TestLog(){print("TestMgr2" + i);}}

测试

public class Main : MonoBehaviour
{private void Start(){TestMgr2.Instance.TestLog();}}

缺点

因为很容易被破坏单例模式的唯一性
1.挂载多个脚本
2.切换场景回来时,由于场景放置了挂载脚本的对象,回到该场景时 又会有一个该单例模式对象
3.还可以通过代码动态的添加多个该脚本 也会破坏唯一性

修改Awake


/// <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,实现动态挂载脚本


/// <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脚本的类名 为对象改名 这样再编辑器中可以明确的看到该//单例模式脚本对象依附的GameObjectobj.name = typeof(T).ToString();//动态挂载对应的 单例模式脚本instance = obj.AddComponent<T>();//过场景时不移除对象 保证它在整个游戏生命周期中都存在DontDestroyOnLoad(obj);}return instance;}}}

Test2Mgr2继承单例模式基类

public class Test2Mgr2 : SingletonAutoMono<Test2Mgr2>
{public void TestLog(){print("Test2Mgr2");}
}

测试

public class Main : MonoBehaviour
{private void Start(){Test2Mgr2.Instance.TestLog();}}

潜在的安全问题

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

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


http://www.ppmy.cn/devtools/126853.html

相关文章

Git教程

Git教程 使用 git 在本地初始化 新建一个目录&#xff0c;用于存放下载下来的项目 进入新建的文件夹&#xff0c;右键选择“Git Bash Here” ​​ 点击之后可以看到下面的界面&#xff0c; git 的基础配置&#xff0c;作用是告诉 git 你是谁&#xff0c;你输入的信息将出现…

信道复用技术

一.概括 二.说明 信道复用技术&#xff1a;“复用”是一种将若干个彼此独立的信号&#xff0c;合并为一个可在同一信道上同时传输的复合信号的方法。比如&#xff0c;传输的语音信号的频谱一般在300~3400Hz内&#xff0c;为了使若干个这种信号能在同一信道上传输&#xff0c;可…

RHCE--at,crontab例行性工作

一&#xff1a;安装at &#xff08;1&#xff09;配置yum仓库&#xff1a;以配置网络源举例&#xff1a; 先在/etc/yum.repos.d/ 目录下创建一个以.repo结尾的文件 vim /etc/yum.repos.d/aliyun.repo 写入可以在阿里云镜像站查找appstream和baseos的地址阿里巴巴开源镜像站…

QML tableView设置role为index的问题

项目中&#xff0c;需要将一个tableview的第一列表示为索引&#xff0c;且索引需从1开始。于是编写代码如下&#xff1a; 下面展示一些 内联代码片。 ListModel {id: com_model;} GE_TableView {id: tableview;height: 510;anchors.top: root.top;anchors.left: root.left;anc…

从头开始的可视化数据 matplotlib:初学者努力绘制数据图

从头开始学习使用 matplotlib 可视化数据&#xff0c;对于初学者来说&#xff0c;可能会有些挑战&#xff0c;但 matplotlib 的核心理念非常清晰&#xff1a;绘制图表需要了解如何设置图形、坐标轴以及如何用数据填充它们。我们可以通过一些简单的例子来逐步介绍基本步骤。 1. …

Windows 修改 Alt+Tab 键 切换 新版 Microsoft Edge 单个标签页/窗口

Windows 10 修改 AltTab 键 切换 新版 Microsoft Edge 单个标签页/窗口 解决方案&#xff1a;在 Windows 设置 的搜索框中 搜索 alt&#xff0c;选择 选择按下 AltTab 时显示的窗口和选项卡&#xff0c;将 按 Alt Tab 将显示 选为 仅打开的窗口 详细过程&#xff1a; 在 Win…

太速科技-732-基于3U VPX的AGX orin GPU计算主板

732-基于3U VPX的AGX orin GPU计算主板 一、产品概述 基于3U VPX的 AGX orin GPU计算主板是LINUX环境下软件开发等理想工具。拥有VPX标准连接器和特性的接口。是用于视频处理&#xff0c;支持PCIE、USB、RS422、RS232、网口、等综合性的信号计算主板。 产品结构完全满足VIT…

新版idea菜单栏展开与合并

新版idea把菜单栏合并了看着很是不习惯&#xff0c;找了半天原来在这里展开 ① 点击文件 -> 设置 ② 点击外观与行为 -> 外观 -> 合并主菜单和窗口标题 然后确定&#xff0c;重启即可