unity3d中的单例模式
单例模式(singleton pattern)大家都不陌生,今天主要是和大家探讨一下单例模式在unity中的实现,比起一般的单例,unity中有些他的特点。
最普通的单例:(样式一)
public class Singleton { static Singleton instance; public static Singleton Instance { get { if (instance == null) { instance = new Singleton (); } return instance; } } }
unity单例模式二:
但是unity的所有脚本都必须挂在一个gameobject上,否则无法执行,你这个单例中若只是一些数据,那倒没关系,但我相信绝大多数单例模式都不会只包含数据,若只要实现包含数据的功能,用全局静态变量就行了,说到这里加一句,有些盆友喜欢用单例脚本当做全局脚本来用,那其实是违背单例模式的初衷的…
好,我们来实现以下挂到gameobject的单例(模式二):
public class UnitySingleton : MonoBehaviour { static UnitySingleton instance; public static UnitySingleton Instance { get { if (instance == null) { GameObject obj = new GameObject (); instance = obj.AddComponent (typeof(UnitySingleton)); } return instance; } } }
unity单例模式三:
那如果我的游戏里有很多单例脚本,每个脚本都这么写岂不是很麻烦?岂不是很违背oo思想?_,那我们来设计一个泛型类:
public class UnitySingleton<T> : MonoBehaviour where T : Component { private static T _instance; public static T Instance { get { if (_instance == null) { instance = FindObjectOfType (typeof(T)) as T; if (_instance == null) { GameObject obj = new GameObject (); obj.hideFlags = HideFlags.HideAndDontSave;//隐藏实例化的new game object,下同 _instance = obj.AddComponent (typeof(T)); } } return _instance; } } }
这样一来,场景中需要单例化的脚本只要简单的继承这个类就可以了
public class Manager : UnitySingleton<Manager> { public string testText = "hello Sinngleton!"; }
manager单例脚本将在第一次实例化时自动创建,当然,你是看不到他的呵呵,但是底部的debuglog出卖了他…:
public class SingletonTest : MonoBehaviour { // Use this for initialization void Start () { Debug.Log(Manager.Instance.testText); } }
unity单例模式四:
最后一个问题就是,我希望我的所有单例脚本在场景变化后依然存在,那自然是用DontDestroyOnLoad,直接上脚本:
using UnityEngine; public class UnitySingleton<T> : MonoBehaviour where T:Component { private static T _instance; public static T Instance { get{ if(_instance == null){ _instance = FindObjectOfType(typeof(T)) as T; if(_instance == null){ GameObject obj = new GameObject (); //obj.hideFlags = HideFlags.DontSave; obj.hideFlags = HideFlags.HideAndDontSave; _instance =(T) obj.AddComponent(typeof(T)); } } return _instance; } } public virtual void Awake() { DontDestroyOnLoad(this.gameObject); if(_instance == null){ _instance = this as T; } else{ Destroy(gameObject); } } }
至此,所有单例模式已经全部探讨完了,单例模式是最简单的设计模式,概念上没什么难懂的,只不过在unity中实现起来需要注意一下,
单例模式的作用:
这一模式的目的是使得类的一个对象成为系统中的唯一实例。
单例模式也是一种比较常见的设计模式,它到底能带给我们什么好处呢?其实无非是三个方面的作用:
第一、控制资源的使用,通过线程同步来控制资源的并发访问;
第二、控制实例产生的数量,达到节约资源的目的。
第三、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。
单例模式的实现方式:懒汉单例类和饿汉单例类
· 懒汉单例类
它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。
懒汉模式只在外部对象第一次请求实例的时候才去创建。
· 饿汉式单例
该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。
我们对比一下懒汉模式和饿汉模式的优缺点:
懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。
饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。
这两种模式对于初始化较快,占用资源少的轻量级对象来说,没有多大的性能差异。但是对于初始化慢,占用资源多的重量级对象来说,就会有比较明显的差别了。所以,对重量级对象应用饿汉模式,类加载时速度慢,但运行时速度快;懒汉模式则与之相反,类加载时速度快,但运行时第一次获得对象的速度慢。
数据库连接池属于重量级资源,一个应用中只需要保留一份即可,既节省了资源又方便管理。所以数据库连接池采用单例模式进行设计会是一个非常好的选择。
实际上,配置信息类、管理类、控制类、门面类、代理类通常被设计为单例类。像Java的Struts、Spring框架,.Net的Spring.Net框架,以及Php的Zend框架都大量使用了单例模式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
2019-10-20 菜鸟学习初级教程-----强烈推荐(看完后成黑客拉)