Files
Ipseity-Demo/Assets/Unheimlich_POC/Scripts/Features/Dialogue/Runtime/DialogueTriggerZone.cs
T

153 lines
4.5 KiB
C#

using UnityEngine;
using Unheimlich.Features.Dialogue.Data;
using Unheimlich.Features.Dialogue;
using Unheimlich.Features.Dialogue.UI;
using Unheimlich.Core.Events;
namespace Unheimlich.Features.Dialogue
{
/// <summary>
/// Trigger zone that starts a dialogue sequence when player enters.
/// Supports pause/resume on exit/enter and optional one-time triggering.
/// </summary>
public class DialogueTriggerZone : TriggerZoneBase
{
[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;
protected override bool IsRetriggerable => _isRetriggerable;
[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 DialogueStateHandler _dialogueState;
protected override void Awake()
{
base.Awake();
_dialogueState = new DialogueStateHandler(this);
if (_floatingWordAnchor == null)
_floatingWordAnchor = transform;
}
protected override void OnPlayerEntered(Collider playerCollider)
{
if (_dialogueState.IsCompleted && !_isRetriggerable)
return;
if (_dialogueState.HasPausedDialogue)
{
_dialogueState.ResumeDialogue();
}
else if (!_hasTriggered || (_isRetriggerable && _dialogueState.IsCompleted))
{
TriggerDialogue();
}
}
protected override void OnPlayerExited(Collider playerCollider)
{
if (_pauseOnExit && DialogueManager.Instance != null && DialogueManager.Instance.IsDialogueActive)
{
if ((Object)DialogueManager.Instance.CurrentOwner == this)
_dialogueState.PauseDialogue();
}
}
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;
DialogueManager.Instance.StartConversation(
_conversation,
_floatingWordAnchor,
_animationSettings,
_localDialogueUI,
this,
_enableBlurEffect
);
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
}
private void OnDialogueCompleted(object owner)
{
if ((Object)owner == this)
{
_dialogueState.MarkAsCompleted();
if (_isRetriggerable)
{
_hasTriggered = false;
_dialogueState.AllowRetrigger();
}
}
if (DialogueManager.Instance != null)
DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted;
}
public void ResetTrigger()
{
_hasTriggered = false;
_dialogueState.Reset();
ResetZone();
}
private void OnDestroy()
{
if (DialogueManager.Instance != null)
DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted;
}
private void OnValidate()
{
if (_localDialogueUI == null)
Debug.LogWarning($"[DialogueTriggerZone] '{gameObject.name}' has no Local Dialogue UI assigned. Assign the appropriate DialogueUI prefab variant (World, NPC, Room, Screen, etc.).", this);
}
private void OnDrawGizmosSelected()
{
if (_floatingWordAnchor != null)
{
Gizmos.color = Color.cyan;
Gizmos.DrawWireSphere(_floatingWordAnchor.position, 0.2f);
}
}
}
}