63 lines
2.3 KiB
C#
63 lines
2.3 KiB
C#
using System.Collections;
|
||
using UnityEngine;
|
||
using BaseGames.Core;
|
||
using BaseGames.Core.Events;
|
||
|
||
namespace BaseGames.Player
|
||
{
|
||
/// <summary>
|
||
/// 监听 EVT_CheckpointRespawn,将玩家瞬移至最近检查点坐标。
|
||
/// 通过淡出 → 移位 → 淡入实现无视觉跳变的传送。
|
||
///
|
||
/// 挂载在玩家根节点(与 Rigidbody2D 同一 GameObject)。
|
||
/// </summary>
|
||
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<ICheckpointService>();
|
||
if (svc != null && svc.HasCheckpoint)
|
||
{
|
||
// 清零速度后移位,防止物理残留动量导致滑步
|
||
var rb = GetComponent<Rigidbody2D>();
|
||
if (rb != null)
|
||
{
|
||
rb.velocity = Vector2.zero;
|
||
rb.position = svc.CheckpointPosition;
|
||
}
|
||
else
|
||
{
|
||
transform.position = svc.CheckpointPosition;
|
||
}
|
||
}
|
||
|
||
_onFadeInRequest?.Raise();
|
||
}
|
||
}
|
||
}
|