using BaseGames.Core.Events;
using UnityEngine;
namespace BaseGames.World
{
///
/// 区域到达触发器(架构 22_QuestChallengeModule §3 扩展)。
/// 挂在场景中的 2D 触发碰撞体上,玩家进入时广播 EVT_AreaReached 事件,
/// 驱动 ReachAreaObjective(markerTag 模式)的任务目标进度。
///
/// 使用方式:
/// 1. 在目标区域创建空 GameObject,添加 Collider2D(勾选 IsTrigger)。
/// 2. 挂上 TriggerZone,填写 markerTag(与 ReachAreaObjective.markerTag 保持一致)。
/// 3. 将 EVT_AreaReached 事件频道资产拖入 _onAreaReached 字段。
/// 4. 将 QuestManager 同一 _onAreaReached 频道字段也引用同一资产即可联通。
///
[RequireComponent(typeof(Collider2D))]
public class TriggerZone : MonoBehaviour
{
[Header("区域标识")]
[Tooltip("区域唯一标记(如 \"ZONE_ForestEntry\")。需与 ReachAreaObjective.markerTag 保持完全一致。")]
[SerializeField] private string _markerTag;
[Tooltip("触发后是否只生效一次(推荐勾选,防止重复广播)。")]
[SerializeField] private bool _triggerOnce = true;
[Header("玩家层级")]
[Tooltip("玩家所在的物理层,用于过滤非玩家碰撞体进入。只有属于此层的碰撞体才触发广播。")]
[SerializeField] private LayerMask _playerLayer;
[Header("事件频道")]
[Tooltip("EVT_AreaReached 事件频道(StringEventChannelSO)。触发时以 markerTag 为 payload 广播。\n" +
"需与 QuestManager._onAreaReached 字段引用同一资产。")]
[SerializeField] private StringEventChannelSO _onAreaReached;
private bool _triggered;
/// 区域唯一标记(只读)。供编辑器工具(QuestModule 批量验证)交叉比对使用。
public string MarkerTag => _markerTag;
private void OnTriggerEnter2D(Collider2D other)
{
if (_triggered) return;
if (string.IsNullOrEmpty(_markerTag)) return;
if (((1 << other.gameObject.layer) & _playerLayer.value) == 0) return;
_onAreaReached?.Raise(_markerTag);
if (_triggerOnce) _triggered = true;
}
/// 重置触发状态(如读档/重新进入关卡时调用)。
public void ResetTrigger() => _triggered = false;
#if UNITY_EDITOR
private void OnDrawGizmos()
{
if (string.IsNullOrEmpty(_markerTag)) return;
Gizmos.color = new Color(0.2f, 0.8f, 0.4f, 0.25f);
var col = GetComponent();
if (col != null) Gizmos.DrawWireSphere(col.bounds.center, 0.3f);
}
private void OnDrawGizmosSelected()
{
var col = GetComponent();
if (col == null) return;
Gizmos.color = new Color(0.2f, 0.9f, 0.4f, 0.5f);
Gizmos.DrawWireCube(col.bounds.center, col.bounds.size);
UnityEditor.Handles.Label(
col.bounds.center + Vector3.up * (col.bounds.extents.y + 0.2f),
string.IsNullOrEmpty(_markerTag) ? "(未设置 markerTag)" : _markerTag);
}
#endif
}
}