2026-06-05 14:57:25 +07:00
|
|
|
using UnityEngine;
|
|
|
|
|
using TMPro;
|
|
|
|
|
using PrimeTween;
|
|
|
|
|
|
|
|
|
|
namespace Hallucinate.UI
|
|
|
|
|
{
|
|
|
|
|
public class ChatBubble : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
[SerializeField] private TextMeshProUGUI textDisplay;
|
|
|
|
|
[SerializeField] private CanvasGroup canvasGroup;
|
|
|
|
|
[SerializeField] private RectTransform bubbleRect;
|
|
|
|
|
|
|
|
|
|
private Transform mainCameraTransform;
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
{
|
2026-06-05 18:46:19 +07:00
|
|
|
if (canvasGroup != null) canvasGroup.alpha = 0;
|
|
|
|
|
// gameObject.SetActive(false); // Bỏ dòng này để tránh tắt nhầm NPC gốc
|
2026-06-05 14:57:25 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LateUpdate()
|
|
|
|
|
{
|
2026-06-05 18:46:19 +07:00
|
|
|
// Tìm Camera nếu chưa có (Tránh lỗi Null nếu Camera chưa spawn hoặc bị xóa)
|
|
|
|
|
if (mainCameraTransform == null)
|
|
|
|
|
{
|
|
|
|
|
if (Camera.main != null) mainCameraTransform = Camera.main.transform;
|
|
|
|
|
else return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-05 14:57:25 +07:00
|
|
|
// Billboard effect
|
|
|
|
|
transform.LookAt(transform.position + mainCameraTransform.rotation * Vector3.forward, mainCameraTransform.rotation * Vector3.up);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Show(string text, float duration = 4f)
|
|
|
|
|
{
|
|
|
|
|
gameObject.SetActive(true);
|
|
|
|
|
textDisplay.text = text;
|
|
|
|
|
|
|
|
|
|
// Animation using PrimeTween
|
|
|
|
|
PrimeTween.Sequence.Create()
|
|
|
|
|
.Group(Tween.Alpha(canvasGroup, 1f, 0.3f))
|
|
|
|
|
.Group(Tween.Scale(bubbleRect, Vector3.zero, Vector3.one, 0.4f, Ease.OutBack))
|
|
|
|
|
.Chain(Tween.Delay(duration))
|
|
|
|
|
.Chain(Tween.Alpha(canvasGroup, 0f, 0.5f))
|
|
|
|
|
.OnComplete(() => gameObject.SetActive(false));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|