第3种:上一篇介绍了的静态类, 本篇介绍游戏中常用的单例组件。它与静态类最大的区别是可以利用MonoBehaviour的事件回调,协程等特性。比较适合于游戏的管理器类、事件分发等系统并共外界访问调用。
MonoBehaviour脚本组件单例模式继承基类脚本如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Author:W
* MonoBehaviour组件单例模式
*/
public class MonoSingleton<T> : MonoBehaviour where T: MonoSingleton<T>
{
private bool _isActive = true;
void OnDestroy()
{
_isActive = false;
}
void OnApplicationQuit()
{
_isActive = false;
}
/// <summary>
/// 供外界调用单例对象时,可以先去验证该单例对象的有效性
/// 特别是针对在调用者的OnDestroy()方法时,容易弹出错误
/// “有些对象在关闭场景时没有清理干净(是否在OnDestroy()中衍生了新的GameObjects?)”
/// </summary>
public static bool IsActive
{
get
{
if (_instance == null)
return false;
return _instance._isActive;
}
}
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
//获取当前场景中所有的T类型的游戏对象
T[] allInstances = GameObject.FindObjectsOfType<T>();
//当前场景中存在这样的实例
if (allInstances != null)
{
//只存在一个
if (allInstances.Length == 1)
{
_instance = allInstances[0];
return _instance;
}//存在多个时
else if (allInstances.Length > 1)
{
//全部销毁
for (int i = 0; i < allInstances.Length; i++)
{
T curIns = allInstances[i];
GameObject.Destroy(curIns.gameObject);
}
}
}
//当前场景中不存在T实例对象,则进行创建
GameObject go = new GameObject(typeof(T).Name);
_instance = go.AddComponent<T>();
//设定该单例组件不会随着场景地切换而销毁
DontDestroyOnLoad(_instance.gameObject);
}
return _instance;
}
set
{
_instance = value as T;
}
}
void Awake()
{
//设定该单例组件不会随着场景地切换而销毁
DontDestroyOnLoad(this.gameObject);
}
}
具体测试单例组件脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* Author:W
* Mono单例继承测试
*/
public class SingletonTest : MonoSingleton<SingletonTest> {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
总结:单例模式虽然让方便了模块系统之间的访问通信,但不能过度使用,会造成代码之间的耦合度比较高。其实,对于一般的系统之间的通信,可以封装出一个游戏共用的消息系统来满足游戏各子系统之间的通信交互。