using BaseGames.Core;
using BaseGames.Core.Events;
using UnityEngine;
namespace BaseGames.World
{
///
/// 房间/场景过渡触发器。玩家进入触发器或按交互键时,广播 。
///
/// 通过 控制过渡演出:
///
/// - Room:极短淡出,无加载画面,适合相邻房间边界。
/// - Scene:完整淡出 + 加载画面,适合大区域切换。
///
/// 如需门动画,请改用 组件,它会在动画完成后内部触发本组件。
///
///
[RequireComponent(typeof(Collider2D))]
public class RoomTransition : MonoBehaviour, IInteractable
{
[Header("本传送门标识")]
[SerializeField] private string _transitionId; // 本出口唯一 ID(供 SceneLoader 写入复活点)
[Header("目标")]
[SerializeField] private string _targetSceneAddress; // Addressable key(目标场景)
[SerializeField] private string _targetTransitionId; // 目标房间出生点 ID
[Header("过渡类型")]
[Tooltip("Seamless:无缝切换,流式系统标准选项,绝大多数房间门使用此类型。\n" +
"AtmosphericFade:短暂淡出 + 区域名提示,适合跨大区域边界。\n" +
"Room:极短淡出,不走流式系统(仅用于非流式独立场景切换)。\n" +
"Scene:完整淡出 + 加载画面,大区域/地图间传送专用。")]
[SerializeField] private TransitionType _transitionType = TransitionType.Seamless;
[Header("触发方式")]
[SerializeField] private bool _autoTrigger = true; // true = 玩家进入触发器自动触发
[Header("钥匙物品校验")]
[SerializeField] private bool _requiresKeyItem; // 是否需要持有指定钥匙物品
[SerializeField] private string _requiredItemId; // 钥匙物品 ID(_requiresKeyItem = true 时生效)
[Header("世界状态")]
[SerializeField] private WorldStateRegistry _worldState;
// ── IInteractable ─────────────────────────────────────────────────────
public bool CanInteract => !_autoTrigger;
public string InteractPrompt => _transitionType == TransitionType.Scene ? "前往下一区域" : "进入";
public void Interact(Transform player) => RequestTransition();
public void OnPlayerEnterRange(Transform player) { }
public void OnPlayerExitRange() { }
// ── Auto Trigger ──────────────────────────────────────────────────────
private void OnTriggerEnter2D(Collider2D other)
{
if (!_autoTrigger) return;
if (!other.CompareTag("Player")) return;
RequestTransition();
}
/// 触发过渡。可由触发器、交互系统或 调用。
public void RequestTransition()
{
if (_requiresKeyItem && !HasItem(_requiredItemId)) return;
var request = new SceneLoadRequest
{
SceneName = _targetSceneAddress,
EntryTransitionId = _targetTransitionId,
TransitionType = _transitionType,
IsRespawn = false,
};
var sceneService = ServiceLocator.GetOrDefault();
if (sceneService != null)
{
sceneService.RequestTransition(request);
return;
}
Debug.LogWarning("[RoomTransition] 无法发送过渡请求:ISceneService 未在 ServiceLocator 中注册。", this);
}
/// 检查玩家是否持有指定物品(通过 WorldStateRegistry.IsCollected 检查)。
private bool HasItem(string itemId)
{
if (string.IsNullOrEmpty(itemId)) return true;
if (_worldState == null)
{
Debug.LogWarning($"[RoomTransition] WorldStateRegistry 未配置,钥匙 {itemId} 检查跳过");
return false;
}
return _worldState.IsCollected(itemId);
}
private void OnDrawGizmos()
{
var col = GetComponent();
if (col == null) return;
Gizmos.color = _transitionType == TransitionType.Scene
? new Color(1f, 0.6f, 0f, 0.6f) // 橙色:大区域切换
: new Color(0f, 1f, 0.5f, 0.6f); // 绿色:房间切换
Gizmos.DrawWireCube(transform.position, col.bounds.size);
}
}
}