using System;
using System.Collections.Generic;
using UnityEngine;
namespace AlicizaX
{
///
/// 所有单例的统一管理器。
///
[DefaultExecutionOrder(-9999)]
public sealed class SingletonManager : MonoBehaviour
{
private static SingletonManager _instance;
private readonly Dictionary _singletons = new();
public static SingletonManager Instance
{
get
{
if (_instance == null)
{
// 查找是否已有实例
_instance = FindFirstObjectByType();
if (_instance == null)
{
var obj = new GameObject("[SingletonManagers]");
_instance = obj.AddComponent();
DontDestroyOnLoad(obj);
}
}
return _instance;
}
}
///
/// 注册一个单例。
///
internal void Register(T instance) where T : Component
{
var type = typeof(T);
if (!_singletons.ContainsKey(type))
{
_singletons[type] = instance;
instance.transform.SetParent(transform, false);
}
}
///
/// 注销单例。
///
internal void Unregister(T instance) where T : Component
{
var type = typeof(T);
if (_singletons.TryGetValue(type, out var current) && current == instance)
_singletons.Remove(type);
}
///
/// 获取一个已注册的单例(若不存在则返回 null)
///
public T Get() where T : Component
{
_singletons.TryGetValue(typeof(T), out var result);
return result as T;
}
}
///
/// 泛型单例基类。
/// 自动注册到 SingletonManager。
/// 支持动态创建与销毁。
///
public abstract class Singleton : MonoBehaviour where T : Component
{
private static T _instance;
private static readonly object _lock = new();
public static T Instance
{
get
{
if (_instance != null) return _instance;
lock (_lock)
{
if (_instance != null) return _instance;
// 检查 SingletonManager 是否存在
var manager = SingletonManager.Instance;
// 查找场景中是否已经存在该类型
_instance = manager.Get();
if (_instance == null)
{
var obj = new GameObject(typeof(T).Name);
_instance = obj.AddComponent();
manager.Register(_instance);
}
return _instance;
}
}
}
protected virtual void Awake()
{
if (_instance == null)
{
_instance = this as T;
SingletonManager.Instance.Register(_instance);
}
else if (_instance != this)
{
Destroy(gameObject);
return;
}
}
protected virtual void OnDestroy()
{
if (_instance == this)
{
SingletonManager.Instance.Unregister(this as T);
_instance = null;
}
}
}
}