Files
zeling_v2/Assets/_Game/Scripts/VFX/RegionLightController.cs

115 lines
4.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using BaseGames.Core.Events;
namespace BaseGames.VFX
{
/// <summary>
/// 区域进出时平滑切换 Global Light 2D 颜色和强度。
/// 挂在 Persistent 场景 [Lighting] GameObject 上,监听 OnRegionEntered 事件频道。
/// </summary>
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
// ────────────────────────────────────────────────────────────────────────────
/// <summary>
/// 区域 ID → Global Light 2D 颜色 + 强度映射表。
/// 资产路径Assets/ScriptableObjects/VFX/VFX_RegionLightCatalog.asset
/// </summary>
[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;
/// <summary>根据 regionId 查找对应的灯光配置。</summary>
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;
}
}
}