单例模式 Singleton
单例模式 是一个非常复杂的话题,在此,我们尝试使用 C#了解 Unity 中 Singleton 的基础知识和各种实现。
1.概述
单例模式是一种基本的设计模式。实现 单例模式 的类将确保在任何时候都只存在对象的 唯一 实例。对于不需要在游戏过程中多次复制的内容,建议使用单例。这对于 GameManager 或 AudioController 等控制器类非常有用。
2.方案
在 Unity 中有几种实现 单例模式 的方式,我们将在本教程中进行一些实现:
2.1 最简单的实现
以下:
1 | public class SingletonController : MonoBehaviour |
上面的代码是单例的最简单的实现,但是有一些问题需要我们解决
- Singleton 在 Unity 场景中不是持久的。
- 所有可执行代码都必须附加到层次结构中的
GameObject。 - 不建议
Controller.Instance在任何Awake()方法中调用 Singleton ,因为我们不知道Awake()将通过所有脚本执行的顺序,我们可能会以Null Reference Exception结束。 - 此代码仅适用于
SingletonController类,但如果您想要另一个单例控制器,例如AudioController,我们必须将相同的代码复制粘贴到AudioController类中,并对工作进行一些小的更改,但这会导致 样板代码 。
以下我们依次解决这些问题:
2.2 解决问题1
问题1即:
- Singleton 在 Unity 场景中不是持久的。
这个很容易修复,只需添加 DontDestroyOnLoad(gameObject) ,即:
1 | public class SingletonController : MonoBehaviour |
以上。
2.3 解决问题2和3
问题2和3即:
- 所有可执行代码都必须附加到层次结构中的
GameObject。 - 不建议
Controller.Instance在任何Awake()方法中调用 Singleton ,因为我们不知道Awake()将通过所有脚本执行的顺序,我们可能会以Null Reference Exception结束。
对于这两个问题,我们必须在需要的时候创建 Singleton,这意味着我们必须在 Unity 中延迟实例化 SingletonController;
以下:
1 | public class SingletonController : MonoBehaviour |
上面的代码解决了两个不同的问题:
它首先在场景中搜索 SingletonController 的实例,如果没有找到 SingletonController 组件,则创建一个新的 GameObject并附加一个SingletonController 组件。因此我们不需要将 SingletonController 预先存在于场景中,并且此代码还将销毁它找到的任何其他副本。
其次,因为在这个实现中我们懒惰地实例化单例,所以现在我们不用担心空引用异常。
2.4 解决问题4
问题4即:
- 此代码仅适用于
SingletonController类,但如果您想要另一个单例控制器,例如AudioController,我们必须将相同的代码复制粘贴到AudioController类中,并对工作进行一些小的更改,但这会导致 样板代码 。
第四个问题是样板代码,所以我们需要 Singleton 的通用实现来解决这个问题
1 | public class GenericSingletonClass<T> : MonoBehaviour where T : Component |
所以有了这个类,我们可以使任何类成为单例,而无需重复代码。只需从 GenericSingletonClass 继承您的类 ,它就可以使用了。
例如:
1 | public class MyAudioController : GenericSingletonClass<MyAudioController> |
以上。
3.结论
Singleton 有点复杂,但它在游戏开发中扮演着非常重要的角色。在复杂的游戏中,我们可能需要很多 Singleton,所以最好有一个 Singleton 的通用实现,以减少代码重复。第四个解决方案处理大部分问题。
同样的,我们也可以直接使用以下解决方案:
直接给出了相应的 Singleton 解决方案和示例代码。

以上。