using System; using System.Collections; using UnityEngine; using UnityEngine.Rendering.Universal; using BaseGames.Core.Events; namespace BaseGames.VFX { /// /// 区域进出时平滑切换 Global Light 2D 颜色和强度。 /// 挂在 Persistent 场景 [Lighting] GameObject 上,监听 OnRegionEntered 事件频道。 /// public class RegionLightController : MonoBehaviour { [SerializeField] private Light2D _globalLight; [SerializeField] private RegionLightCatalogSO _catalog; [SerializeField] private StringEventChannelSO _onRegionEntered; [SerializeField] private float _transitionDuration = 1.5f; private Coroutine _colorCoroutine; private Coroutine _intensityCoroutine; private readonly CompositeDisposable _subs = new(); private void Awake() { Debug.Assert(_catalog != null, "[RegionLightController] _catalog 未赋值,请在 Inspector 中指定 RegionLightCatalogSO。", this); Debug.Assert(_globalLight != null, "[RegionLightController] _globalLight 未赋值,请在 Inspector 中绑定 Light2D。", this); } private void OnEnable() { _onRegionEntered?.Subscribe(OnRegionEntered).AddTo(_subs); } private void OnDisable() { _subs.Clear(); } private void OnRegionEntered(string regionId) { if (!_catalog.TryGet(regionId, out var config)) return; if (_colorCoroutine != null) StopCoroutine(_colorCoroutine); if (_intensityCoroutine != null) StopCoroutine(_intensityCoroutine); _colorCoroutine = StartCoroutine(TweenColor(_globalLight.color, config.Color, _transitionDuration)); _intensityCoroutine = StartCoroutine(TweenIntensity(_globalLight.intensity, config.Intensity, _transitionDuration)); } // ── Coroutine helpers ──────────────────────────────────────────────────── private IEnumerator TweenColor(Color from, Color to, float duration) { float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; _globalLight.color = Color.Lerp(from, to, Mathf.Clamp01(elapsed / duration)); yield return null; } _globalLight.color = to; _colorCoroutine = null; } private IEnumerator TweenIntensity(float from, float to, float duration) { float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; _globalLight.intensity = Mathf.Lerp(from, to, Mathf.Clamp01(elapsed / duration)); yield return null; } _globalLight.intensity = to; _intensityCoroutine = null; } } // ──────────────────────────────────────────────────────────────────────────── // RegionLightCatalogSO // ──────────────────────────────────────────────────────────────────────────── /// /// 区域 ID → Global Light 2D 颜色 + 强度映射表。 /// 资产路径:Assets/ScriptableObjects/VFX/VFX_RegionLightCatalog.asset /// [CreateAssetMenu(menuName = "BaseGames/VFX/RegionLightCatalog")] public class RegionLightCatalogSO : ScriptableObject { [Serializable] public struct RegionLightConfig { public string regionId; public Color Color; [Range(0f, 1f)] public float Intensity; } [SerializeField] private RegionLightConfig[] _entries; /// 根据 regionId 查找对应的灯光配置。 public bool TryGet(string regionId, out RegionLightConfig cfg) { if (_entries != null) { foreach (var e in _entries) { if (e.regionId == regionId) { cfg = e; return true; } } } cfg = default; return false; } } }