using UnityEngine; using Unheimlich.Features.Dialogue.Data; using Unheimlich.Features.Dialogue; using Unheimlich.Features.Dialogue.UI; namespace Unheimlich.Features.Dialogue { /// /// Trigger zone that starts a dialogue sequence when player enters. /// Supports pause/resume on exit/enter and optional one-time triggering. /// [RequireComponent(typeof(Collider))] public class DialogueTriggerZone : MonoBehaviour { [Header("Dialogue Reference")] [Tooltip("DialogueConversation to use for this trigger zone")] [SerializeField] private DialogueConversation _conversation; [Header("Trigger Settings")] [Tooltip("Can the dialogue be retriggered after completion")] [SerializeField] private bool _isRetriggerable = false; [SerializeField] private bool _requirePlayerTag = true; [SerializeField] private string _playerTag = "Player"; [Header("Distance Check")] [Tooltip("Pause dialogue if player exits the trigger zone")] [SerializeField] private bool _pauseOnExit = true; [Header("Floating Word Anchor")] [SerializeField] private Transform _floatingWordAnchor; [Header("Animation Settings")] [SerializeField] private DialogueAnimationSettings _animationSettings; [Header("UI Reference")] [Tooltip("Local DialogueUI for this trigger zone. Uses DialogueManager's UI if null")] [SerializeField] private DialogueUI _localDialogueUI; [Header("Blur Effect")] [Tooltip("Enable blur effect when dialogue starts")] [SerializeField] private bool _enableBlurEffect = true; private bool _hasTriggered = false; private Collider _triggerCollider; private DialogueStateHandler _dialogueState; private void Awake() { _triggerCollider = GetComponent(); _dialogueState = new DialogueStateHandler(this); if (!_triggerCollider.isTrigger) { Debug.LogWarning($"{gameObject.name}: Collider should be marked as Trigger!", this); _triggerCollider.isTrigger = true; } if (_floatingWordAnchor == null) _floatingWordAnchor = transform; } private void OnTriggerEnter(Collider other) { if (_requirePlayerTag && !other.CompareTag(_playerTag)) return; if (_dialogueState.IsCompleted && !_isRetriggerable) return; if (_dialogueState.HasPausedDialogue) { _dialogueState.ResumeDialogue(); if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null) DialogueBlurEffectURP.Instance.ShowBlur(); } else if (!_hasTriggered || (_isRetriggerable && _dialogueState.IsCompleted)) { TriggerDialogue(); } } private void OnTriggerExit(Collider other) { if (_requirePlayerTag && !other.CompareTag(_playerTag)) return; if (_pauseOnExit && DialogueManager.Instance != null && DialogueManager.Instance.IsDialogueActive) { if ((Object)DialogueManager.Instance.CurrentOwner == this) { _dialogueState.PauseDialogue(); if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null) DialogueBlurEffectURP.Instance.HideBlur(); } } } private void TriggerDialogue() { if (DialogueManager.Instance == null) { Debug.LogError("DialogueManager not found in scene!", this); return; } if (_conversation == null) { Debug.LogError($"{gameObject.name}: No conversation assigned!", this); return; } _hasTriggered = true; if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null) { DialogueBlurEffectURP.Instance.ShowBlur(); } DialogueManager.Instance.StartConversation( _conversation, _floatingWordAnchor, _animationSettings, _localDialogueUI, this ); DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted; } private void OnDialogueCompleted(object owner) { if ((Object)owner == this) { _dialogueState.MarkAsCompleted(); if (_isRetriggerable) { _hasTriggered = false; _dialogueState.AllowRetrigger(); } if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null) DialogueBlurEffectURP.Instance.HideBlur(); } if (DialogueManager.Instance != null) DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted; } public void ResetTrigger() { _hasTriggered = false; _dialogueState.Reset(); } private void OnDestroy() { if (DialogueManager.Instance != null) DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted; } private void OnDrawGizmosSelected() { Collider col = GetComponent(); if (col != null) { Gizmos.color = _hasTriggered ? Color.gray : Color.yellow; Gizmos.matrix = transform.localToWorldMatrix; if (col is BoxCollider box) Gizmos.DrawWireCube(box.center, box.size); else if (col is SphereCollider sphere) Gizmos.DrawWireSphere(sphere.center, sphere.radius); } if (_floatingWordAnchor != null) { Gizmos.color = Color.cyan; Gizmos.DrawWireSphere(_floatingWordAnchor.position, 0.2f); } } } }