using System.Collections; using UnityEngine; using BaseGames.Core; using BaseGames.Core.Events; namespace BaseGames.Player { /// /// 监听 EVT_CheckpointRespawn,将玩家瞬移至最近检查点坐标。 /// 通过淡出 → 移位 → 淡入实现无视觉跳变的传送。 /// /// 挂载在玩家根节点(与 Rigidbody2D 同一 GameObject)。 /// public class CheckpointRespawnHandler : MonoBehaviour { [Header("事件 - 监听")] [Tooltip("EVT_CheckpointRespawn — 由 LethalTrap 在玩家存活且场景有检查点时触发")] [SerializeField] private VoidEventChannelSO _onCheckpointRespawn; [Header("事件 - 触发")] [Tooltip("EVT_FadeOutRequest — 传送前淡出屏幕")] [SerializeField] private VoidEventChannelSO _onFadeOutRequest; [Tooltip("EVT_FadeInRequest — 传送后淡入屏幕")] [SerializeField] private VoidEventChannelSO _onFadeInRequest; [Header("配置")] [Tooltip("淡出结束到执行位移之间的等待时长(秒,不受 TimeScale 影响)")] [SerializeField] private float _fadeHalfDuration = 0.2f; private readonly CompositeDisposable _subs = new(); private void OnEnable() => _onCheckpointRespawn?.Subscribe(OnCheckpointRespawn).AddTo(_subs); private void OnDisable() => _subs.Clear(); private void OnCheckpointRespawn() => StartCoroutine(RespawnCoroutine()); private IEnumerator RespawnCoroutine() { _onFadeOutRequest?.Raise(); yield return new WaitForSecondsRealtime(_fadeHalfDuration); var svc = ServiceLocator.GetOrDefault(); if (svc != null && svc.HasCheckpoint) { // 清零速度后移位,防止物理残留动量导致滑步 var rb = GetComponent(); if (rb != null) { rb.velocity = Vector2.zero; rb.position = svc.CheckpointPosition; } else { transform.position = svc.CheckpointPosition; } } _onFadeInRequest?.Raise(); } } }