// Assets/Scripts/World/Liquid/WaterDangerState.cs using BaseGames.Core.Events; using BaseGames.Player; using UnityEngine; namespace BaseGames.World.Liquid { /// /// 当玩家进入 Water 类型液体且未解锁游泳能力时,触发溺水倒计时。 /// 订阅 EVT_LiquidEntered / EVT_LiquidExited 事件频道。 /// public class WaterDangerState : MonoBehaviour { [SerializeField] private LiquidPhysicsConfigSO _config; [SerializeField] private PlayerStats _playerStats; // 检查 Swim 能力 [SerializeField] private LiquidEventChannelSO _onLiquidEntered; // EVT_LiquidEntered [SerializeField] private LiquidEventChannelSO _onLiquidExited; // EVT_LiquidExited [SerializeField] private FloatEventChannelSO _onDrownProgress; // 0~1 倒计时进度(HUD 用) [SerializeField] private VoidEventChannelSO _onPlayerDrowned; // 触发死亡 private float _drownTimer; private bool _isActive; private readonly CompositeDisposable _subs = new(); private void Awake() { Debug.Assert(_config != null, "[WaterDangerState] _config 未赋值,请在 Inspector 中指定 LiquidPhysicsConfigSO。", this); } private void OnEnable() { _onLiquidEntered?.Subscribe(OnEnterLiquid).AddTo(_subs); _onLiquidExited?.Subscribe(OnExitLiquid).AddTo(_subs); } private void OnDisable() => _subs.Clear(); public void OnEnterLiquid(LiquidEvent evt) { if (evt.LiquidType != nameof(LiquidType.Water)) return; if (_playerStats != null && _playerStats.HasAbility(AbilityType.Swim)) return; _isActive = true; _drownTimer = _config.DrownTime; } public void OnExitLiquid(LiquidEvent evt) { _isActive = false; _drownTimer = _config.DrownTime; _onDrownProgress?.Raise(0f); } private void Update() { if (!_isActive) return; _drownTimer -= Time.deltaTime; float drownTime = _config.DrownTime; _onDrownProgress?.Raise(1f - (_drownTimer / drownTime)); if (_drownTimer <= 0f) { _isActive = false; _onPlayerDrowned?.Raise(); } } } }