|
返回总目录
第六章 基本框架(Framework)
二 单例模式(Singleton)
单例模式,就是指一个类只有一个对象实例。
1 单例(Singleton.cs)
单例大家已经非常熟悉了,这里和一般单例没什么区别。只是多继承了一个IDisposable接口。直接上代码了。
using System;
namespace DR.Book.SRPG_Dev.Framework
{
public abstract class Singleton<T> : IDisposable where T : Singleton<T>, new()
{
private static object s_lock = new object();
private static T s_Instance;
public static T instance
{
get
{
if (s_Instance == null)
{
lock (s_lock)
{
if (s_Instance == null)
{
s_Instance = new T();
}
}
}
return s_Instance;
}
}
public static void Release()
{
if (s_Instance != null)
{
((IDisposable)s_Instance).Dispose();
}
}
protected Singleton()
{
OnConstruct();
}
protected virtual void OnConstruct()
{
}
void IDisposable.Dispose()
{
OnDispose();
s_Instance = null;
}
protected virtual void OnDispose()
{
}
}
}
2 单例组件(UnitySingleton.cs)
单例组件这个东西也是大家非常熟悉的。只是其中,我们把调用DontDestroyOnLoad方法分离成一个组件。
这样当我们忘记哪些物体是DontDestroy的时候,就以是否存在这个组件来判断。
2.1 DontDestroyGameObject.cs
using UnityEngine;
namespace DR.Book.SRPG_Dev.Framework
{
[AddComponentMenu("SRPG/Dont Destroy GameObject")]
public sealed class DontDestroyGameObject : MonoBehaviour
{
private void Awake()
{
GameObject.DontDestroyOnLoad(gameObject);
}
}
}
2.2 单例组件(UnitySingleton.cs)
using UnityEngine;
namespace DR.Book.SRPG_Dev.Framework
{
public abstract class UnitySingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T s_Instance;
public static T instance
{
get
{
if (s_Instance == null)
{
s_Instance = GameObject.FindObjectOfType<T>();
if (s_Instance == null)
{
GameObject go = new GameObject("(singeton)" + typeof(T).Name);
s_Instance = go.AddComponent<T>();
}
if (s_Instance.GetComponent<DontDestroyGameObject>() == null)
{
s_Instance.gameObject.AddComponent<DontDestroyGameObject>();
}
}
return s_Instance;
}
}
public static bool needCreated
{
get { return s_Instance == null; }
}
public static void DestroyInstance()
{
if (s_Instance != null)
{
GameObject.DestroyImmediate(s_Instance.gameObject);
}
}
#region Unity Callback
protected virtual void Awake()
{
if (s_Instance == null)
{
s_Instance = this as T;
}
else if (s_Instance != this)
{
MonoBehaviour.DestroyImmediate(this);
return;
}
if (s_Instance.GetComponent<DontDestroyGameObject>() == null)
{
s_Instance.gameObject.AddComponent<DontDestroyGameObject>();
}
}
protected virtual void OnDestroy()
{
if (s_Instance == this)
{
s_Instance = null;
}
}
#endregion
}
}
在Awake()方法中,如果有多个Instance,那么从第二个开始都会被Destroy掉。
其中,DestroyInstance()方法会直接销毁GameObject,如果你手动将多个单例挂载在同一个物体上,它会直接销毁这些单例组件。
2.3 协程的单例(CoroutineInstance.cs)
在前面已经介绍过了这个文件的作用。
在某些时候物体的activeInHierarchy属性为false时,或者在非MonoBehaviour的类中,我们也想启用协程,那么就可以使用它。类内并不需要其它参数,它只用于启用协程与关闭协程。
namespace DR.Book.SRPG_Dev.Framework
{
public sealed class CoroutineInstance : UnitySingleton<CoroutineInstance>
{
}
}
|