在了解单例模式之前让我们先看看单例模式能干嘛
单例模式在Unity中的应用
在整个游戏中只有一个而你又想可以方便地随时访问它,这时你就可以考虑单例模式了。例如:
- 管理场景切换的脚本
- 管理玩家信息的通用脚本
- 管理游戏中各种常用的UI脚本
- 管理音乐播放的脚本…
什么是单例模式
单例模式(Singleton Pattern):类的实例在内存中只存在一份。一种最简单的设计模式之一,属于创建型模式。它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该对象。
Notice:
- 单例类只能有一个实例;
- 单例类必须自己创建自己的唯一实例;
- 单例类必须给所有其他对象提供这一实例。
单例类的使用
在unity中,分为两种单例类,一种是继承monobehavior的单例,一种是普通的单例。
至于这两种单例类的创建详情推荐大家去下面这个网址学习,其中讲到了单例类的继承
下面是我个人认为比较好的方式(继承monobehvior)来创建一个用于音乐管理的单例脚本。
MusicManager.cs脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
public class MusicManager : MonoBehaviour
{
private static MusicManager current; // 私有静态实例
private void Awake() // 创建实例不能放在Start中,这是由执行顺序决定的
{
if (current != null) // 避免场景重载或者切换时出现多个
{
Destroy(gameObject);
return;
}
current = this; // 创建唯一实例
DontDestroyOnLoad(gameObject); // 若想在场景切换时,单例模式不受任何影响需要加上这句
}
private void OnApplicationQuit()
{
if (current != null)
{
Destroy(gameObject); // 在OnApplicationQuit函数中销毁单例模式
}
}
}
注释内容的详解见
https://blog.csdn.net/ycl295644/article/details/49487361
上述代码如想直接应用在自己的项目需要注意以下几点:
- 创建一个名为MusicManager.cs的C#脚本;
- 在Hierarchy中创建一个【Game Empty】;
- 将MusicManager.cs拖拽至【Game Empty】;
- 当然,为了方便识别,可将【Game Empty】重命名为【Music Manager】
第二种方法:无需继承Monobehavior,但需要另外创建一个脚本来调用该单例类的属性
UIManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIManager
{
//-------- 单例模式部分 始
private static UIManager _instance;
public static UIManager Instance // 当UIManager的Instance属性被调用后,自动生成该实例
{
get
{
if (_instance == null)
_instance = new UIManager();
return _instance;
}
}
// 构造函数
private UIManager()
{
Test(); // 放一些单例实例创建后需要运行的代码
}
//------ 单例模式部分 终
public void Test()
{
Debug.Log("test success");
}
}
GameRoot.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameRoot : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
UIManager.Instance.Test();
}
}
Hints:
GameRoot.cs 需要作为一个unity对象的脚本组件存在,才能保证在运行时顺利生成 UIManager 类 来进行UI的管理。
单例类的优缺点
该部分原文链接:https://blog.csdn.net/tableview/article/details/14125943
优点
-
单例模式提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。
-
由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
-
允许可变数目的实例。基于单例模式我们可以进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例,既节省系统资源,又解决了单例单例对象共享过多有损性能的问题。
缺点
-
由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
-
单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
-
现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。