重构
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Architecture.Variables
|
||||
{
|
||||
/// <summary>
|
||||
/// 共享布尔变量(ScriptableObject 资产)。常用于暂停、开关等状态。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Architecture/Variables/Bool", fileName = "NewBoolVariable")]
|
||||
public class BoolVariable : ScriptableObject, Architecture.IVariable
|
||||
{
|
||||
[SerializeField] private bool _value;
|
||||
|
||||
[Tooltip("进入 Play Mode 时的初始值,由 VariableRegistry 在每次启动游戏时自动恢复,防止跨局状态泄漏")]
|
||||
[SerializeField] private bool _defaultValue;
|
||||
|
||||
public bool Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value == value) return;
|
||||
_value = value;
|
||||
OnValueChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<bool> OnValueChanged;
|
||||
|
||||
public void SetValue(bool value) => Value = value;
|
||||
|
||||
/// <summary>将运行时值重置为 _defaultValue(每次进入 Play Mode 时由 VariableRegistry 自动调用)。</summary>
|
||||
public void ResetToDefault()
|
||||
{
|
||||
_value = _defaultValue;
|
||||
OnValueChanged?.Invoke(_value);
|
||||
}
|
||||
|
||||
[ContextMenu("Reset To Default")]
|
||||
public void Reset() => ResetToDefault();
|
||||
|
||||
private void OnEnable() => VariableRegistry.Register(this);
|
||||
private void OnDisable()
|
||||
{
|
||||
VariableRegistry.Unregister(this);
|
||||
OnValueChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DXsdsCquB3geiEyhIkY2aFLJpbGuThlr6ky9pgS1Nnrno7aw3ZWk4Uc=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Architecture.Variables
|
||||
{
|
||||
/// <summary>
|
||||
/// 共享浮点变量(ScriptableObject 资产)。
|
||||
/// 任何系统可读取 / 写入,并由 OnValueChanged 事件驱动 UI 刷新,
|
||||
/// 替代 MonoBehaviour 字段跨系统传递与逐帧反射读取。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Architecture/Variables/Float", fileName = "NewFloatVariable")]
|
||||
public class FloatVariable : ScriptableObject, Architecture.IVariable
|
||||
{
|
||||
[SerializeField] private float _value;
|
||||
|
||||
[Tooltip("进入 Play Mode 时的初始值,由 VariableRegistry 在每次启动游戏时自动恢复,防止跨局状态泄漏")]
|
||||
[SerializeField] private float _defaultValue;
|
||||
|
||||
public float Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (Mathf.Approximately(_value, value)) return;
|
||||
_value = value;
|
||||
OnValueChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<float> OnValueChanged;
|
||||
|
||||
public void SetValue(float value) => Value = value;
|
||||
public void ApplyChange(float amount) => Value += amount;
|
||||
|
||||
/// <summary>将运行时值重置为 _defaultValue(每次进入 Play Mode 时由 VariableRegistry 自动调用)。</summary>
|
||||
public void ResetToDefault()
|
||||
{
|
||||
_value = _defaultValue;
|
||||
OnValueChanged?.Invoke(_value);
|
||||
}
|
||||
|
||||
[ContextMenu("Reset To Default")]
|
||||
public void Reset() => ResetToDefault();
|
||||
|
||||
private void OnEnable() => VariableRegistry.Register(this);
|
||||
private void OnDisable()
|
||||
{
|
||||
VariableRegistry.Unregister(this);
|
||||
OnValueChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DntJsS6uBnP85uXqLRZji/q5FaD10/2h7b+TePWWB+tWhBvOfF7TELg=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Architecture.Variables
|
||||
{
|
||||
/// <summary>
|
||||
/// 共享整数变量(ScriptableObject 资产)。常用于血量、得分、魂灵数等。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Architecture/Variables/Int", fileName = "NewIntVariable")]
|
||||
public class IntVariable : ScriptableObject, Architecture.IVariable
|
||||
{
|
||||
[SerializeField] private int _value;
|
||||
|
||||
[Tooltip("进入 Play Mode 时的初始值,由 VariableRegistry 在每次启动游戏时自动恢复,防止跨局状态泄漏")]
|
||||
[SerializeField] private int _defaultValue;
|
||||
|
||||
public int Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value == value) return;
|
||||
_value = value;
|
||||
OnValueChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<int> OnValueChanged;
|
||||
|
||||
public void SetValue(int value) => Value = value;
|
||||
public void ApplyChange(int amount) => Value += amount;
|
||||
|
||||
/// <summary>将运行时值重置为 _defaultValue(每次进入 Play Mode 时由 VariableRegistry 自动调用)。</summary>
|
||||
public void ResetToDefault()
|
||||
{
|
||||
_value = _defaultValue;
|
||||
OnValueChanged?.Invoke(_value);
|
||||
}
|
||||
|
||||
[ContextMenu("Reset To Default")]
|
||||
public void Reset() => ResetToDefault();
|
||||
|
||||
private void OnEnable() => VariableRegistry.Register(this);
|
||||
private void OnDisable()
|
||||
{
|
||||
VariableRegistry.Unregister(this);
|
||||
OnValueChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: W3octHuoWnnZAVrTuCOazcbeHxKYqo5abD3dZ/KJEBmkydHqGDyV9qE=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DHMdty+tWygUNpW3ZTnsgECvyUsf7TZS/Bowuhd8nTjV1gGiSvKO6z4=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Architecture.Variables
|
||||
{
|
||||
/// <summary>
|
||||
/// 共享 Vector3 变量(ScriptableObject 资产)。常用于位置、回声中心等。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Architecture/Variables/Vector3", fileName = "NewVector3Variable")]
|
||||
public class Vector3Variable : ScriptableObject, Architecture.IVariable
|
||||
{
|
||||
[SerializeField] private Vector3 _value;
|
||||
|
||||
[Tooltip("进入 Play Mode 时的初始值,由 VariableRegistry 在每次启动游戏时自动恢复,防止跨局状态泄漏")]
|
||||
[SerializeField] private Vector3 _defaultValue;
|
||||
|
||||
public Vector3 Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
_value = value;
|
||||
OnValueChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<Vector3> OnValueChanged;
|
||||
|
||||
public void SetValue(Vector3 value) => Value = value;
|
||||
|
||||
/// <summary>将运行时值重置为 _defaultValue(每次进入 Play Mode 时由 VariableRegistry 自动调用)。</summary>
|
||||
public void ResetToDefault()
|
||||
{
|
||||
_value = _defaultValue;
|
||||
OnValueChanged?.Invoke(_value);
|
||||
}
|
||||
|
||||
[ContextMenu("Reset To Default")]
|
||||
public void Reset() => ResetToDefault();
|
||||
|
||||
private void OnEnable() => VariableRegistry.Register(this);
|
||||
private void OnDisable()
|
||||
{
|
||||
VariableRegistry.Unregister(this);
|
||||
OnValueChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: BnIa4SyuVyiKWphMPOJ0zNHa5e8eoX06FNossjB+7+Ma8SaSRkVd14E=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user