51 lines
2.3 KiB
C#
51 lines
2.3 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace Architecture
|
||
{
|
||
/// <summary>
|
||
/// 共享变量统一接口:所有 Variable 资产实现它,注册表才能统一重置。
|
||
/// </summary>
|
||
public interface IVariable
|
||
{
|
||
void ResetToDefault();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 共享变量注册表 —— 运行时状态防泄漏的核心。
|
||
///
|
||
/// <b>问题</b>:ScriptableObject 资产在 Editor 下跨 Play Mode 域重载会持久化其序列化值。
|
||
/// 例如 PlayerHealth.Value 在游玩中变为 0 后退出 Play Mode,若残留为 0,
|
||
/// 下次进入 Play Mode 可能直接触发死亡(或分数残留、开关状态错乱)。
|
||
///
|
||
/// <b>解决</b>:每个 Variable 在 OnEnable 时自动注册;每次进入 Play Mode(域加载前)
|
||
/// 由 [RuntimeInitializeOnLoadMethod] 统一调用 ResetToDefault(),
|
||
/// 将运行时值恢复到设计器设置的 _defaultValue,杜绝跨局状态泄漏。
|
||
///
|
||
/// 注意:RuntimeInitializeLoadType.BeforeSceneLoad 在整个 Play Mode 生命周期内只触发一次,
|
||
/// 因此同一局内跨场景加载(SceneManager.LoadScene)不会重置变量,分数等跨场景共享状态可正常保留。
|
||
/// </summary>
|
||
public static class VariableRegistry
|
||
{
|
||
private static readonly HashSet<IVariable> _variables = new HashSet<IVariable>();
|
||
|
||
public static void Register(IVariable variable)
|
||
{
|
||
_variables.Add(variable);
|
||
// 注册即重置:解决 [RuntimeInitializeOnLoadMethod(BeforeSceneLoad)] 在 SO 资产
|
||
// 尚未 OnEnable 注册前就执行 ResetAll(此时 _variables 为空)导致重置无效的问题。
|
||
// 无论 ResetAll 何时触发,变量在「上线」瞬间都会被恢复到 _defaultValue,
|
||
// 杜绝退出 Play Mode 后 PlayerHealth 残留 0、再次进入直接触发死亡的跨局泄漏。
|
||
variable.ResetToDefault();
|
||
}
|
||
public static void Unregister(IVariable variable) => _variables.Remove(variable);
|
||
|
||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||
public static void ResetAll()
|
||
{
|
||
foreach (var v in _variables)
|
||
v.ResetToDefault();
|
||
}
|
||
}
|
||
}
|