153 lines
3.9 KiB
C#
153 lines
3.9 KiB
C#
using TMPro;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Displays interaction prompts on screen when looking at an IInteractable object.
|
|
/// Place this on a UI Canvas with a TextMeshProUGUI or Text component.
|
|
/// </summary>
|
|
public class InteractionUI : MonoBehaviour
|
|
{
|
|
[Header("UI References")]
|
|
[Tooltip("Text component to display the prompt (e.g. 'Press [Left Click] to Open Door').")]
|
|
[SerializeField] private TextMeshProUGUI promptText;
|
|
|
|
[Tooltip("Optional panel or parent container to hide when not looking at an interactable.")]
|
|
[SerializeField] private GameObject promptContainer;
|
|
|
|
[Tooltip("Optional prefix before the prompt text (e.g. '[L-Click] ').")]
|
|
[SerializeField] private string inputHintPrefix = "[L-Click] ";
|
|
|
|
[Header("Dialogue / Subtitle UI")]
|
|
[Tooltip("Optional separate Text component for dialogue/subtitles. If unassigned, promptText is used.")]
|
|
[SerializeField] private TextMeshProUGUI dialogueText;
|
|
[SerializeField] private GameObject dialogueContainer;
|
|
|
|
[Header("Player Controller Reference")]
|
|
[Tooltip("Reference to the PlayerController. If left empty, it will find the player automatically.")]
|
|
[SerializeField] private PlayerController playerController;
|
|
|
|
public static InteractionUI Instance { get; private set; }
|
|
|
|
private float dialogueTimer = 0f;
|
|
private bool isShowingDialogue = false;
|
|
|
|
private void Awake()
|
|
{
|
|
Instance = this;
|
|
|
|
if (playerController == null)
|
|
{
|
|
playerController = FindAnyObjectByType<PlayerController>();
|
|
}
|
|
|
|
HidePrompt();
|
|
HideDialogue();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
// Handle Dialogue timer
|
|
if (isShowingDialogue)
|
|
{
|
|
dialogueTimer -= Time.deltaTime;
|
|
if (dialogueTimer <= 0f)
|
|
{
|
|
HideDialogue();
|
|
}
|
|
}
|
|
|
|
if (playerController == null) return;
|
|
|
|
// If menu is open, hide the prompt
|
|
if (playerController.IsMenuOpen)
|
|
{
|
|
HidePrompt();
|
|
return;
|
|
}
|
|
|
|
IInteractable hovered = playerController.CurrentHoveredInteractable;
|
|
|
|
if (hovered != null)
|
|
{
|
|
string prompt = hovered.GetPrompt();
|
|
if (!string.IsNullOrEmpty(prompt))
|
|
{
|
|
ShowPrompt(inputHintPrefix + prompt);
|
|
}
|
|
else
|
|
{
|
|
HidePrompt();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HidePrompt();
|
|
}
|
|
}
|
|
|
|
public void ShowDialogue(string text, float duration = 4f)
|
|
{
|
|
if (string.IsNullOrEmpty(text)) return;
|
|
|
|
isShowingDialogue = true;
|
|
dialogueTimer = duration;
|
|
|
|
TextMeshProUGUI targetText = dialogueText != null ? dialogueText : promptText;
|
|
GameObject targetContainer = dialogueContainer != null ? dialogueContainer : promptContainer;
|
|
|
|
if (targetContainer != null)
|
|
{
|
|
targetContainer.SetActive(true);
|
|
}
|
|
|
|
if (targetText != null)
|
|
{
|
|
targetText.text = text;
|
|
targetText.gameObject.SetActive(true);
|
|
}
|
|
}
|
|
|
|
public void HideDialogue()
|
|
{
|
|
isShowingDialogue = false;
|
|
dialogueTimer = 0f;
|
|
|
|
if (dialogueContainer != null)
|
|
{
|
|
dialogueContainer.SetActive(false);
|
|
}
|
|
|
|
if (dialogueText != null)
|
|
{
|
|
dialogueText.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
private void ShowPrompt(string message)
|
|
{
|
|
if (promptContainer != null)
|
|
{
|
|
promptContainer.SetActive(true);
|
|
}
|
|
|
|
if (promptText != null)
|
|
{
|
|
promptText.text = message;
|
|
promptText.gameObject.SetActive(true);
|
|
}
|
|
}
|
|
|
|
private void HidePrompt()
|
|
{
|
|
if (promptContainer != null)
|
|
{
|
|
promptContainer.SetActive(false);
|
|
}
|
|
|
|
if (promptText != null)
|
|
{
|
|
promptText.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|