102 lines
3.3 KiB
C#
102 lines
3.3 KiB
C#
using UnityEngine;
|
||
|
||
namespace AlicizaX
|
||
{
|
||
/// <summary>
|
||
/// Mono 服务基类(不自动注册,适合需要手动控制注册时机的场景)。
|
||
/// </summary>
|
||
public abstract class MonoServiceBehaviour : MonoBehaviour, IMonoService
|
||
{
|
||
public ServiceContext Context { get; private set; }
|
||
|
||
public bool IsInitialized { get; private set; }
|
||
|
||
protected ServiceWorld World => Context.World;
|
||
|
||
protected ServiceScope Scope => Context.Scope;
|
||
|
||
void IService.Initialize(ServiceContext context)
|
||
{
|
||
if (IsInitialized)
|
||
throw new System.InvalidOperationException($"{GetType().FullName} is already initialized.");
|
||
|
||
Context = context;
|
||
IsInitialized = true;
|
||
OnServiceInitialize();
|
||
}
|
||
|
||
void IService.Destroy()
|
||
{
|
||
if (!IsInitialized) return;
|
||
|
||
OnServiceDestroy();
|
||
IsInitialized = false;
|
||
Context = default;
|
||
}
|
||
|
||
protected virtual void OnServiceInitialize() { }
|
||
|
||
protected virtual void OnServiceDestroy() { }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Mono 服务基类(自动注册到 <typeparamref name="TScope"/>)。
|
||
/// <para>
|
||
/// 场景服务:<c>_dontDestroyOnLoad = false</c>(默认),销毁时自动注销。<br/>
|
||
/// 跨场景服务:<c>_dontDestroyOnLoad = true</c>,首个实例持久化并注册;
|
||
/// 后续场景中出现的重复实例自动销毁自身。
|
||
/// </para>
|
||
/// <para>
|
||
/// 子类通过 <see cref="OnAwake"/> 执行额外的 Awake 逻辑,
|
||
/// 通过 <see cref="OnServiceInitialize"/> 执行注册后的初始化,
|
||
/// 通过 <see cref="OnServiceDestroy"/> 执行注销前的清理。
|
||
/// </para>
|
||
/// </summary>
|
||
public abstract class MonoServiceBehaviour<TScope> : MonoServiceBehaviour
|
||
where TScope : class
|
||
{
|
||
[SerializeField] private bool _dontDestroyOnLoad = false;
|
||
|
||
// 注意:使用 Start 而非 Awake 注册,确保 GameServiceRoot.Awake(创建 World)必然先于此执行。
|
||
// DefaultExecutionOrder 会影响所有生命周期(含 Awake),用 Start 可彻底规避执行顺序陷阱。
|
||
private void Awake()
|
||
{
|
||
OnAwake();
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
var scope = AppServices.GetOrCreateScope<TScope>();
|
||
|
||
// 跨场景重复实例检测:契约已被占用则销毁自身
|
||
if (scope.HasContract(GetType()))
|
||
{
|
||
Destroy(gameObject);
|
||
return;
|
||
}
|
||
|
||
// Defer DontDestroyOnLoad until after the duplicate check so rejected
|
||
// duplicates are never moved to the DontDestroyOnLoad scene.
|
||
if (_dontDestroyOnLoad)
|
||
DontDestroyOnLoad(gameObject);
|
||
|
||
scope.Register(this);
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
if (!IsInitialized) return;
|
||
if (!AppServices.HasWorld) return;
|
||
if (!AppServices.TryGetScope<TScope>(out var scope)) return;
|
||
|
||
scope.Unregister(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在 Awake 阶段执行(早于 Start 中的自动注册)。
|
||
/// 适合缓存组件引用等不依赖服务系统的初始化。
|
||
/// </summary>
|
||
protected virtual void OnAwake() { }
|
||
}
|
||
}
|