- TD-13: IQuestManager.CompleteQuest 改用 IRewardTarget,移除 using BaseGames.Player - TD-14: HurtFlashController 缓存 WaitForSeconds(_waitForFlash 字段) - TD-16: LiquidType 枚举迁移至 BaseGames.Core.Events;LiquidEvent.LiquidType 改为枚举直接比较 - TD-17: DeathScreenController 移除失效的 _onPlayerDied 订阅,改为 OnEnable 直接启动延迟显示 影响文件: IQuestManager.cs / HurtFlashController.cs / LiquidType.cs(迁移) / LiquidEvent.cs / LiquidZone.cs / WaterDangerState.cs / UnderwaterPostProcessingController.cs / UnderwaterAudioController.cs / DeathScreenController.cs 评审文档: Docs/Review/FrameworkReview_2026_May_v11.md(综合评分 9.30/10)
70 lines
2.4 KiB
C#
70 lines
2.4 KiB
C#
// 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 != 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();
|
||
}
|
||
}
|
||
}
|
||
}
|