using System.Collections;
using Animancer;
using BaseGames.Core;
using BaseGames.Core.Events;
using UnityEngine;
namespace BaseGames.World
{
///
/// 门过渡组件。挂载在有物理门对象的 GameObject 上。
///
/// 触发流程:
///
/// - 玩家进入触发器或按交互键 → 播放 开门动画
/// - 动画完成后发出 ,类型由 决定
/// - 目标场景出生点侧的 被 引用,
/// 由外部调用 播放玩家进入门的过渡动画
///
///
///
/// 若不需要门动画,直接使用 即可。
///
///
[RequireComponent(typeof(Collider2D))]
public class DoorTransition : MonoBehaviour, IInteractable
{
[Header("目标")]
[SerializeField] private string _targetSceneAddress;
[SerializeField] private string _targetTransitionId;
[Header("过渡类型")]
[Tooltip("Room:极短淡出,无加载画面。\nScene:完整淡出 + 加载画面。")]
[SerializeField] private TransitionType _transitionType = TransitionType.Room;
[Header("触发方式")]
[Tooltip("true = 玩家进入触发器自动触发;false = 需要玩家按交互键。")]
[SerializeField] private bool _autoTrigger = false;
[Header("门动画")]
[SerializeField] private AnimancerComponent _animancer;
[Tooltip("玩家从外侧进入时播放的开门动画(出口侧)。留空则跳过动画直接过渡。")]
[SerializeField] private AnimationClip _openClip;
[Tooltip("玩家从内侧走出时播放的动画(入口侧,由 PlayerSpawnPoint 在玩家出生后触发)。留空则跳过。")]
[SerializeField] private AnimationClip _enterClip;
[Header("钥匙物品校验")]
[SerializeField] private bool _requiresKeyItem;
[SerializeField] private string _requiredItemId;
[Header("世界状态")]
[SerializeField] private WorldStateRegistry _worldState;
private bool _triggered;
// ── IInteractable ─────────────────────────────────────────────────────
public bool CanInteract => !_autoTrigger;
public string InteractPrompt => "进入";
public void Interact(Transform player) => TryTrigger();
public void OnPlayerEnterRange(Transform player) { }
public void OnPlayerExitRange() { }
// ── 触发 ──────────────────────────────────────────────────────────────
private void OnTriggerEnter2D(Collider2D other)
{
if (!_autoTrigger) return;
if (!other.CompareTag("Player")) return;
TryTrigger();
}
private void TryTrigger()
{
if (_triggered) return;
if (_requiresKeyItem && !HasItem(_requiredItemId)) return;
_triggered = true;
StartCoroutine(OpenAndTransition());
}
private void OnDisable() => _triggered = false;
// ── 动画流程 ──────────────────────────────────────────────────────────
private IEnumerator OpenAndTransition()
{
if (_animancer != null && _openClip != null)
{
var state = _animancer.Play(_openClip);
yield return state; // 等待动画完成
}
var request = new SceneLoadRequest
{
SceneName = _targetSceneAddress,
EntryTransitionId = _targetTransitionId,
TransitionType = _transitionType,
IsRespawn = false,
};
var sceneService = ServiceLocator.GetOrDefault();
if (sceneService != null)
{
sceneService.RequestTransition(request);
yield break;
}
Debug.LogWarning("[DoorTransition] 无法发送过渡请求:ISceneService 未在 ServiceLocator 中注册。", this);
}
///
/// 玩家从门内侧走出时的动画(由出生点侧的 在玩家出生后调用)。
/// 若未配置 则静默跳过。
///
public void PlayEnterAnimation()
{
if (_animancer != null && _enterClip != null)
_animancer.Play(_enterClip);
}
// ── 辅助 ──────────────────────────────────────────────────────────────
private bool HasItem(string itemId)
{
if (string.IsNullOrEmpty(itemId)) return true;
if (_worldState == null)
{
Debug.LogWarning($"[DoorTransition] WorldStateRegistry 未配置,钥匙 {itemId} 检查跳过");
return false;
}
return _worldState.IsCollected(itemId);
}
private void OnDrawGizmos()
{
var col = GetComponent();
if (col == null) return;
// 紫色区分门过渡
Gizmos.color = new Color(0.7f, 0.3f, 1f, 0.7f);
Gizmos.DrawWireCube(transform.position, col.bounds.size);
Gizmos.color = new Color(0.7f, 0.3f, 1f, 0.3f);
Gizmos.DrawCube(transform.position, col.bounds.size);
}
}
}