当前位置: 首页 > article >正文

Unity小框架之单例模式基类

                单例模式(Singleton Pattern)是一种常用的创建型设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点。它常用于需要控制资源访问、共享配置或管理全局状态的场景(如数据库连接池、日志管理器、应用配置等)。        

单例模式的核心思想

  1. 私有构造函数:防止外部通过 new 创建多个实例。
  2. 静态私有实例:类内部持有唯一的实例。
  3. 全局访问方法:提供一个静态方法(如 getInstance())获取唯一实例。

        下面来介绍一下在C#和unity中实现的单例模式基类,你某些需要进行单例模式化的脚本,就可以继承这个基类然后就实现了自己的单例化,那你就可以在其他地方进行使用了。

一、最基本的单例基类

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//单例模式基类模块//1.C#泛型的知识
//2.设计模式中 单例模式的知识
public class BaseManager <T> where T : new()
{//单例模式private static T instance;public static T GetInstance(){if (instance == null){instance = new T();}return instance;}
}

使用方法:

例如下面这个脚本,我们创建了一个NewBehaviourScript的脚本,然后直接继承单例模式基类,如果其他地方需要调用,就直接使用就行

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class NewBehaviourScript : BaseManager<NewBehaviourScript>
{   void Start(){Debug.Log(NewBehaviourScript.GetInstance());}
}

再来一个示例:

// 子类继承 BaseManager,并满足 new() 约束
public class GameManager : BaseManager<GameManager>
{// 必须有一个公共无参构造函数public GameManager() {Debug.Log("GameManager Created");}public void Init(){Debug.Log("GameManager Initialized");}
}// 使用方式
void Start()
{
//可以在你项目中的任意一个地方进行使用GameManager manager = GameManager.GetInstance();manager.Init();// 问题:外部仍然可以 new GameManager(),破坏单例!GameManager another = new GameManager(); // 这是允许的 但是你自己选择可以不实现 后面我们还有保护措施 使得外部不能实例化
}

二、继承了Mono的单例模式基类

继承了Mono那么我们就可以使用Unity的生命周期函数了

代码:

public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T _instance;// 使用属性替代 GetInstance(),更符合 C# 习惯public static T Instance{get{// 如果实例不存在,尝试查找或创建if (_instance == null){_instance = FindObjectOfType<T>();// 如果场景中没有,自动创建一个新的 GameObjectif (_instance == null){GameObject obj = new GameObject(typeof(T).Name);_instance = obj.AddComponent<T>();}}return _instance;}}protected virtual void Awake(){// 如果实例已存在且不是当前对象,销毁自身if (_instance != null && _instance != this){Destroy(gameObject);return;}// 初始化实例_instance = this as T;// 按需设置跨场景保留DontDestroyOnLoad(gameObject); }
}

还有个简单的版本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//C#泛型的知识
//设计模式中 单例模式的知识//继承了MonoBehaviour的 单例模式对象 需要我们自己保证它的唯一性
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T instance;public static T GetInstance(){//继承了MonoBehaviour的类,不能直接new//只能通过拖动到对象上 或者通过加脚本的api AddComponent//U3d内部会帮助我们直接实例化return instance;}protected virtual void Awake(){instance = this as T;}
}

请注意:继承了这个单例模式基类的话,是不能够自己去new的你只能拖拽到物体身上。

示例:

这样改进是为了让我们在没有继承Mono的时候,仍然能使用生命周期函数

public class AudioManager : SingletonMono<AudioManager>
{public void PlaySound(string clipName){Debug.Log("Playing: " + clipName);}
}// 使用方式
void Start()
{AudioManager.Instance.PlaySound("BackgroundMusic");
}

示例:

using UnityEngine;// 继承 SingletonMono,并指定自身为泛型类型 T
public class SoundManager : SingletonMono<SoundManager>
{// 自定义音频方法public void PlaySound(string clipName){Debug.Log("播放音效: " + clipName);}// 初始化音频资源(在 Awake 中调用)protected override void Awake(){base.Awake(); // 调用基类的 Awake 方法,确保单例赋值Debug.Log("SoundManager 初始化完成");}
}

创建这样一个空物体,挂在脚本后,其他的类里面才能使用

使用:

public class PlayerController : MonoBehaviour
{private void Start(){// 获取 SoundManager 实例并调用方法SoundManager.Instance.PlaySound("跳跃音效");}private void Update(){// 直接通过 Instance 属性访问if (Input.GetKeyDown(KeyCode.Space)){SoundManager.Instance.PlaySound("射击音效");}}
}

三、继承了mono并且已经自己实例化的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T instance;public static T GetInstance(){if (instance == null){GameObject obj = new GameObject();//设置对象的名字为脚本名字obj.name = typeof(T).ToString();//让这个单例模式对象过场景不移除//因为 单例模式对象 往往是存在于整个程序生命周期中的DontDestroyOnLoad(obj);instance = obj.AddComponent<T>();}return instance;}}

使用示例:

在继承了这个类的脚本里面直接使用内部的函数即可

public class NetworkManager : SingletonAutoMono<NetworkManager>
{public void Connect(string serverIP){Debug.Log($"连接到服务器: {serverIP}");}protected override void Awake(){base.Awake(); // 调用基类 Awake 确保单例初始化Debug.Log("网络管理器已初始化");}
}// 使用方式
void Start()
{NetworkManager.Instance.Connect("127.0.0.1");
}

注意事项

  1. 手动挂载与自动创建的冲突

    • 如果手动在场景中挂载脚本,需确保只有一个实例。
    • 优化后的代码会优先使用手动挂载的实例。
  2. 跨场景行为

    • 若需某个单例仅在特定场景存在,移除 DontDestroyOnLoad

相关文章:

Unity小框架之单例模式基类

单例模式&#xff08;Singleton Pattern&#xff09;是一种常用的创建型设计模式&#xff0c;其核心目标是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。它常用于需要控制资源访问、共享配置或管理全局状态的场景&#xff08;如数据库连接池、日志管理器、应用配置…...

随机过程的基本概念机有限维分布的数字特征

随机过程的基本概念及有限维分布的数字特征&#xff1a;从理论到应用 在现代科学与技术的众多领域中&#xff0c;随机过程的身影无处不在&#xff0c;它如同一位神秘的幕后操纵者&#xff0c;影响着我们生活的方方面面。今天&#xff0c;咱们就一起来深入探究随机过程的基本概…...

langchain如何并行调用运行接口

文章目录 概要并行化步骤 概要 RunnableParallel 原语本质上是一个字典&#xff0c;其值是运行接口&#xff08;或可以被强制转换为运行接口的事物&#xff0c;如函数&#xff09;。它并行运行所有值&#xff0c;并且每个值都使用 RunnableParallel 的整体输入进行调用。最终返…...

如何理解语义web中提到本体的概念

在语义Web&#xff08;Semantic Web&#xff09;中&#xff0c;“本体”&#xff08;Ontology&#xff09;是一个核心概念&#xff0c;它源自哲学中的“存在论”&#xff0c;但在计算机科学中被重新定义为一种形式化的、共享的领域知识模型。本体的核心目标是解决数据之间的语义…...

基于大模型的声带息肉预测及诊疗方案优化研究报告

目录 一、引言 1.1 研究背景与目的 1.2 研究意义与创新点 二、大模型预测原理与方法 2.1 大模型技术概述 2.2 数据收集与处理 2.3 模型构建与训练 2.4 模型评估指标 三、术前预测与评估 3.1 息肉特征预测 3.1.1 大小与位置预测 3.1.2 形态与性质预测 3.2 患者身体…...

cesium 实现万级管网数据渲染,及pickImageryLayerFeatures原生方法改写

需求背景解决效果getFeatureInfo 需求背景 在用 geoserver 渲染图层时&#xff0c;会自动触发 GetFeatureInfo &#xff0c;与服务器通信&#xff0c;在万级海量数据渲染下&#xff0c;这个性能消耗就可以感受到了 需要考虑的点&#xff1a; 1.通过enablePickFeatures&#xf…...

基于金融产品深度学习推荐算法详解【附源码】

深度学习算法说明 1、简介 神经网络协同过滤模型(NCF) 为了解决启发式推荐算法的问题&#xff0c;基于神经网络的协同过滤算法诞生了&#xff0c;神经网络的协同过滤算法可以 通过将用户和物品的特征向量作为输入&#xff0c;来预测用户对新物品的评分&#xff0c;从而解决…...

【Linux】centos配置可用的yum源

在 CentOS 系统中配置可用的 YUM 源&#xff08;仓库&#xff09;是保持系统更新和软件包管理的重要步骤。下面是一些步骤和示例&#xff0c;帮助你配置可用的 YUM 源&#xff1a; 1. 备份当前 YUM 仓库配置 首先&#xff0c;备份你当前的 YUM 仓库配置文件&#xff0c;以防万…...

LVS + Keepalived 高可用集群

一、LVSKeepalived 原理 1.1.LVS 负载均衡原理 LVS&#xff08;Linux Virtual Server&#xff09;是一种基于 Linux 内核的负载均衡技术&#xff0c;它通过 IPVS&#xff08;IP Virtual Server&#xff09;模块来实现。LVS 可以将客户端的请求分发到多个后端服务器上&#xf…...

PHP与数据库连接常见问题及解决办法

PHP与数据库连接常见问题及解决办法 在现代Web开发中&#xff0c;PHP与数据库的连接是不可或缺的一部分。无论是构建动态网站、内容管理系统&#xff08;CMS&#xff09;还是电子商务平台&#xff0c;PHP与数据库的交互都是核心功能之一。然而&#xff0c;在实际开发过程中&am…...

HarmonyOS-应用程序框架基础

应用程序框架与应用模型的区别 应用框架可以看做是应用模型的一种实现方式&#xff0c;开发人员可以用应用模型来描述应用程序的结构和行为的描述&#xff0c;然后使用应用程序框架来实现这些描述。 应用模型 应用模型是一个应用程序的模型&#xff0c;它是一种抽象的描述&a…...

使用 Doris 和 LakeSoul

作为一种全新的开放式的数据管理架构&#xff0c;湖仓一体&#xff08;Data Lakehouse&#xff09;融合了数据仓库的高性能、实时性以及数据湖的低成本、灵活性等优势&#xff0c;帮助用户更加便捷地满足各种数据处理分析的需求&#xff0c;在企业的大数据体系中已经得到越来越…...

【C语言】函数和数组实践与应用:开发简单的扫雷游戏

【C语言】函数和数组实践与应用&#xff1a;开发简单的扫雷游戏 1.扫雷游戏分析和设计1.1扫雷游戏的功能说明&#xff08;游戏规则&#xff09;1.2游戏的分析与设计1.2.1游戏的分析1.2.2 文件结构设计 2. 代码实现2.1 game.h文件2.2 game.c文件2.3 test.c文件 3. 游戏运行效果4…...

国内Mac,nimi安装homebrew完整过程

安装命令&#xff1a; 常规安装脚本&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 极速安装脚本&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.…...

C++基础——从C语言快速入门

目录 输入输出 标准输出流 ( cout ) 标准输入流 ( cin ) 标准错误流 ( cerr ) 和标准日志流 ( clog ) 编程示例 基本变量类型 宽字符的用法 climits 如何使用 编程示例 注意事项 流程控制 条件语句 循环语句 跳转语句 函数 函数的基本结构 编程示例 函数的组成…...

玩转python:通俗易懂掌握高级数据结构-collections模块之Counter

引言 Counter是Python中collections模块提供的一个强大工具&#xff0c;用于统计可哈希对象的出现次数。它非常适合用于频率统计、词频分析、数据聚合等场景。本文将详细介绍Counter的关键用法和特性&#xff0c;并通过8个丰富的案例帮助读者掌握其应用。 关键用法和特性表格 …...

Windows远程桌面黑屏怎么办?

在使用Windows远程桌面连接另一台电脑时&#xff0c;用户经常会遇到Windows远程桌面黑屏的问题。那么&#xff0c;该如何有效地解决Windows远程桌面黑屏的问题呢&#xff1f;遇到远程桌面连接黑屏的问题时&#xff0c;可以通过在本地组策略编辑器中禁用WDDM图形显示驱动来解决。…...

82.HarmonyOS NEXT 性能优化指南:从理论到实践

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 性能优化指南&#xff1a;从理论到实践 文章目录 HarmonyOS NEXT 性能优化指南&#xff1a;从理论到实践1. 性能优化概述1.1 性能指…...

python笔记2

变量&#xff1a;含义 一个容器&#xff0c;计算机当中的存储空间。 可以理解为一个用于标识或引用数据的名字或标签。 作用&#xff1a; 可以通过定义一个变量来给需要使用多次的数据命名&#xff0c;就像一个标签一样。下次需要使用这个数据时&#xff0c;只需要通过这个变…...

深度学习 Deep Learning 第1章 深度学习简介

第1章 深度学习简介 概述 本章介绍人工智能&#xff08;AI&#xff09;和深度学习领域&#xff0c;讨论其历史发展、关键概念和应用。解释深度学习如何从早期的AI和机器学习方法演变而来&#xff0c;以及如何有效解决之前方法无法应对的挑战。 关键概念 1. 人工智能的演变 …...

Nest系列:NestJS 中 Logger 完全指南:从基础到企业级实践-04

一、Logger 的核心价值 在服务端应用中,日志系统承担着三大核心职责: 系统监控:实时反馈应用健康状态问题追踪:快速定位异常根源行为审计:记录关键业务操作NestJS 内置的日志系统提供了开箱即用的解决方案,支持: ✅ 多日志级别管理 ✅ 上下文感知日志 ✅ 自定义输出格式…...

机器学习 [白板推导](二)[线性回归]

3. 线性回归 3.1. 问题定义 假设两个变量 x ⃗ \vec{x} x 和 y y y 之间存在线性关系&#xff08;例如 y w ⃗ T x ⃗ b y\vec{w}^T\vec{x}b yw Tx b&#xff09;&#xff0c;如何利用数据 D a t a : { ( x ⃗ i , y i ) } i 1 N Data:\{(\vec{x}_i,y_i)\}_{i1}^N Data…...

解决Windows版Redis无法远程连接的问题

&#x1f31f; 解决Windows版Redis无法远程连接的问题 在Windows系统下使用Redis时&#xff0c;很多用户会遇到无法远程连接的问题。尤其是在配置了Redis并尝试通过工具如RedisDesktopManager连接时&#xff0c;可能会报错“Cannot connect to ‘redisconnection’”。今天&am…...

麒麟服务器操作系统Sqlite部署手册

软件简介 SQLite****介绍 SQLite是一个进程内的轻量级嵌入式数据库,它的数据库就是一个文件,实现了自给自足、无服务器、零配置的、事务性的SQL数据库引擎。它是一个零配置的数据库,这就体现出来SQLite与其他数据库的最大的区别:SQLite不需要在系统中配置,直接可以使用。…...

Qt C++ 常用压缩库推荐 快速压缩 解压缩数据

在Qt C中&#xff0c;如果你需要快速压缩和解压缩数据&#xff0c;可以使用以下几种库&#xff1a; 1. zlib 简介: zlib 是一个非常流行的压缩库&#xff0c;支持 DEFLATE 压缩算法。它被广泛用于各种应用程序中&#xff0c;包括Qt。 集成: Qt 本身已经集成了 zlib&#xff0…...

架构师面试(十五):熔断设计

问题 某电商平台经常需要在大促运营活动中暂停评论、退款等业务&#xff0c;基于服务治理的设计理念&#xff0c;我们需要对该电商平台微服务系统的【服务熔断】进行设计&#xff0c;对此下面描述中说法正确的有哪几项呢&#xff1f; A. 服务管控系统管理着平台中所有服务之间…...

解析GNGGA数据,C语言单片机

GPS模块的一帧数据是: $GNGGA,130333.000,4143.43651,N,12328.96485,E,1,14,1.2,93.1,M,0.0,M,,*45 $GNGLL,4143.43651,N,12328.96485,E,130333.000,A,A*4D $GPGSA,A,3,05,07,11,13,20,29,30,195,,,,,2.3,1.2,2.0*05 $BDGSA,A,3,08,13,28,33,38,42,,,,,,,2.3,1.2,2.0*2E $GPG…...

Navicat如何查看密码

近期遇到需要将大部分已存储的navicat数据库转发给其他人&#xff0c;于是乎进行导出文件 奈何对方不用navicat&#xff0c;无法进行文件的导入从而导入链接 搜罗navicat的密码查看&#xff0c;大部分都为php代码解析 以下转载GitHub上看到的一个python代码解析的脚本 这里是对…...

力扣143重排链表

143. 重排链表 给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为&#xff1a; L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的…...

【GPT入门】第24课 langfuse介绍

【GPT入门】第24课 langfuse介绍 1. langfuse概念与作用2. 代码3. 页面效果4. 设计模式1. 装饰器模式2. 上下文管理模式1. langfuse概念与作用 Langfuse是一款专为大规模语言模型(LLM)应用开发设计的开源平台。其作用主要包括以下几个方面: 提升开发效率:通过消除LLM应用构…...