// Assets/Scripts/World/Liquid/UnderwaterPostProcessingController.cs using System.Collections; using BaseGames.Core.Events; using UnityEngine; using UnityEngine.Rendering; namespace BaseGames.World.Liquid { public class UnderwaterPostProcessingController : MonoBehaviour { [SerializeField] private Volume _underwaterVolume; // 水下专属 Volume(WeightMode) [SerializeField] private float _blendInDuration = 0.3f; [SerializeField] private float _blendOutDuration = 0.3f; [SerializeField] private LiquidEventChannelSO _onLiquidEntered; // EVT_LiquidEntered [SerializeField] private LiquidEventChannelSO _onLiquidExited; // EVT_LiquidExited private Coroutine _blendCoroutine; private readonly CompositeDisposable _subs = new(); private void OnEnable() { _onLiquidEntered?.Subscribe(OnLiquidEntered).AddTo(_subs); _onLiquidExited?.Subscribe(OnLiquidExited).AddTo(_subs); } private void OnDisable() => _subs.Clear(); private void OnLiquidEntered(LiquidEvent evt) { if (evt.LiquidType != LiquidType.Water) return; BlendVolume(1f, _blendInDuration); } private void OnLiquidExited(LiquidEvent evt) { if (evt.LiquidType != LiquidType.Water) return; BlendVolume(0f, _blendOutDuration); } private void BlendVolume(float target, float duration) { if (_blendCoroutine != null) StopCoroutine(_blendCoroutine); _blendCoroutine = StartCoroutine(BlendRoutine(target, duration)); } private IEnumerator BlendRoutine(float target, float duration) { if (_underwaterVolume == null) yield break; float start = _underwaterVolume.weight; float elapsed = 0f; while (elapsed < duration) { elapsed += Time.deltaTime; _underwaterVolume.weight = Mathf.Lerp(start, target, elapsed / duration); yield return null; } _underwaterVolume.weight = target; } } }