仅作欣赏~
实际业务中顶多Ins = this(但是得保证挂载得script仅一份啊,不然就没有单例的味道了)
最多加个static、构造、DontDestroy和Destroy,哈哈。
/*
*R0-V1.0
*Modify Date:2020-04-20
*Modifier:ZoJet
*/
using System;
using UnityEngine;
namespace UCL.Core {
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[System.Diagnostics.Conditional("UNITY_EDITOR")]
sealed class ServiceFilterAttribute : Attribute {
public string Name;
public ServiceFilterAttribute(string name) {
Name = name;
}
}
public abstract class MonoSingleton<T> : MonoBehaviour where T : class {
void Awake() {
if(Service<T>.IsRegistered) {
DestroyImmediate(this);
return;
}
#if UNITY_EDITOR
var type = GetType();
var attrs = type.GetCustomAttributes(typeof(ServiceFilterAttribute), true);
if(attrs.Length > 0) {
var sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
var i = attrs.Length - 1;
for(; i >= 0; i--) {
if(System.Text.RegularExpressions.Regex.IsMatch(sceneName, ((ServiceFilterAttribute)attrs[i]).Name)) {
break;
}
}
if(i == -1) {
throw new UnityException(
string.Format("\"{0}\" service cant be used at scene \"{1}\"", type.Name, sceneName));
}
}
#endif
Service<T>.Register(this as T);
OnCreateService();
}
void OnDestroy() {
if(Service<T>.IsRegistered) {
OnDestroyService();
Service<T>.Unregister(this as T);
}
}
protected abstract void OnCreateService();
protected abstract void OnDestroyService();
}
public static class Service<T> where T : class {
static T _instance;
public static bool IsRegistered {
get {
return _instance != null;
}
}
public static T Get() {
if(_instance != null) {
return _instance;
}
var type = typeof(T);
if(type.IsSubclassOf(typeof(ScriptableObject))) {
var list = Resources.FindObjectsOfTypeAll(type);
if(list == null || list.Length == 0) {
throw new UnityException(
string.Format("Service<{0}>.Get() can be used only with exists / loaded asset of this type", type.Name));
}
_instance = list[0] as T;
return _instance;
}
#if UNITY_EDITOR
if(type.IsSubclassOf(typeof(Component)) && !type.IsSubclassOf(typeof(MonoSingleton<T>))){
throw new UnityException(
string.Format("\"{0}\" - invalid type, should be inherited from MonoSingleton", type.Name));
}
#endif
if(type.IsSubclassOf(typeof(MonoSingleton<T>))) {
#if UNITY_EDITOR
if(!Application.isPlaying) {
throw new UnityException(
string.Format("Service<{0}>.Get() can be used only at PLAY mode", type.Name));
}
#endif
new GameObject(
#if UNITY_EDITOR
"_SERVICE_" + type.Name
#endif
).AddComponent(type);
} else {
Register(Activator.CreateInstance(type) as T);
}
return _instance;
}
public static void Register(T instance) {
if(IsRegistered) {
throw new UnityException(
string.Format("Cant register \"{0}\" as service - type already registered", typeof(T).Name));
}
if(instance == null) {
throw new UnityException(
string.Format("Cant register null instance as service"));
}
_instance = instance;
}
public static void Unregister(T instance, bool force = false) {
if(instance == _instance || force) {
_instance = null;
}
}
}
}