Files
zeling_v2/Assets/_Game/Scripts/World/TriggerZone.cs
Joywayer 6eaa83dc71 feat: Round 48 narrative systems improvements
- QuestSO: Add ValidateBranchCycles() DFS detection for branches[].nextQuest loop
- QuestSO: Mark three legacy prerequisite fields with v2.0 removal warning in Tooltip
- IQuestManager: Add QuestLockReason enum + QuestLockInfo struct (strongly-typed lock info)
- IQuestManager: Add GetQuestLockInfo() method to interface; GetQuestLockReason() now delegates to it
- IQuestEventSource: Add OnQuestStateChanged(questId, oldState, newState) unified event
- QuestManager: Implement GetQuestLockInfo(); fire OnQuestStateChanged on all state transitions
- DialogueManager: Add one-frame yield in HandleChoices before ShowChoices (skip-debounce fix)
- DialogueManager: Increment _playbackId in ForceEnd() to invalidate residual choice callbacks
- DialogueSequenceSO: Add UNITY_EDITOR debug log in TryGetActiveVariant on variant match
- WorldStateRegistry: Add OnBatchStateChanged event + BatchMark() batch-write API
- DialogueModule: List badge shows warning indicator for unconditional-shadowing variants
- DialogueModule: BuildVariantsCard shows logic mode (AND/OR) alongside flag conditions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 00:05:15 +08:00

77 lines
3.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BaseGames.Core.Events;
using UnityEngine;
namespace BaseGames.World
{
/// <summary>
/// 区域到达触发器(架构 22_QuestChallengeModule §3 扩展)。
/// 挂在场景中的 2D 触发碰撞体上,玩家进入时广播 EVT_AreaReached 事件,
/// 驱动 ReachAreaObjectivemarkerTag 模式)的任务目标进度。
///
/// 使用方式:
/// 1. 在目标区域创建空 GameObject添加 Collider2D勾选 IsTrigger
/// 2. 挂上 TriggerZone填写 markerTag与 ReachAreaObjective.markerTag 保持一致)。
/// 3. 将 EVT_AreaReached 事件频道资产拖入 _onAreaReached 字段。
/// 4. 将 QuestManager 同一 _onAreaReached 频道字段也引用同一资产即可联通。
/// </summary>
[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;
/// <summary>区域唯一标记只读。供编辑器工具QuestModule 批量验证)交叉比对使用。</summary>
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;
}
/// <summary>重置触发状态(如读档/重新进入关卡时调用)。</summary>
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<Collider2D>();
if (col != null) Gizmos.DrawWireSphere(col.bounds.center, 0.3f);
}
private void OnDrawGizmosSelected()
{
var col = GetComponent<Collider2D>();
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
}
}