Unity之继承MonoBehaviour的单例

仅作欣赏~
实际业务中顶多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;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值