84 lines
3.4 KiB
C#
84 lines
3.4 KiB
C#
using BaseGames.Core.Events;
|
||
using UnityEngine;
|
||
|
||
namespace BaseGames.World
|
||
{
|
||
/// <summary>
|
||
/// 房间传送点。玩家进入触发器或按交互键时,广播 <see cref="SceneLoadRequest"/>,
|
||
/// 由 SceneLoader 监听并执行 Additive 场景加载/卸载。
|
||
/// </summary>
|
||
[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("触发方式")]
|
||
[SerializeField] private bool _autoTrigger = true; // true = 玩家进入触发器自动触发
|
||
|
||
[Header("钥匙物品校验")]
|
||
[SerializeField] private bool _requiresKeyItem; // 是否需要持有指定钥匙物品
|
||
[SerializeField] private string _requiredItemId; // 钥匙物品 ID(_requiresKeyItem = true 时生效)
|
||
|
||
[Header("事件频道")]
|
||
[SerializeField] private SceneLoadRequestEventChannelSO _onSceneLoadRequest;
|
||
|
||
[Header("世界状态")]
|
||
[SerializeField] private WorldStateRegistry _worldState;
|
||
|
||
// ── IInteractable ─────────────────────────────────────────────────────
|
||
public bool CanInteract => !_autoTrigger;
|
||
public string InteractPrompt => "前往下一区域";
|
||
|
||
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();
|
||
}
|
||
|
||
private void RequestTransition()
|
||
{
|
||
if (_requiresKeyItem && !HasItem(_requiredItemId)) return;
|
||
|
||
_onSceneLoadRequest?.Raise(new SceneLoadRequest
|
||
{
|
||
SceneName = _targetSceneAddress,
|
||
EntryTransitionId = _targetTransitionId,
|
||
ShowLoadingScreen = true,
|
||
IsRespawn = false,
|
||
});
|
||
}
|
||
|
||
/// <summary>检查玩家是否持有指定物品(通过 WorldStateRegistry.IsCollected 检查)。</summary>
|
||
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()
|
||
{
|
||
Gizmos.color = new Color(0f, 1f, 0.5f, 0.6f);
|
||
var col = GetComponent<Collider2D>();
|
||
if (col != null)
|
||
Gizmos.DrawWireCube(transform.position, col.bounds.size);
|
||
}
|
||
}
|
||
}
|