Files
zeling_v2/Assets/Scripts/World/Liquid/WaterDangerState.cs
2026-05-12 15:34:08 +08:00

70 lines
2.4 KiB
C#
Raw 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.
// Assets/Scripts/World/Liquid/WaterDangerState.cs
using BaseGames.Core.Events;
using BaseGames.Player;
using UnityEngine;
namespace BaseGames.World.Liquid
{
/// <summary>
/// 当玩家进入 Water 类型液体且未解锁游泳能力时,触发溺水倒计时。
/// 订阅 EVT_LiquidEntered / EVT_LiquidExited 事件频道。
/// </summary>
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();
}
}
}
}