using System.Collections; using TMPro; using Unity.Mathematics; using UnityEngine; using UnityEngine.UI; public class ChatBubble : MonoBehaviour { [SerializeField] private Collider RootParentCollider; [SerializeField] private float3 Offset; [SerializeField] private TextMeshProUGUI speechText; private Image bubbleImage; private bool IsCoroutineRunning; private IEnumerator messageCoroutine; private IEnumerator fadeCoroutine; private Camera Camera; private CanvasGroup canvasGroup; private const float fadeOutDuration = 1.5f; private WaitForSeconds FullOpacityText; private readonly WaitForSeconds FadeDuration = new WaitForSeconds(fadeOutDuration); private void Awake() { bubbleImage = GetComponent(); canvasGroup = GetComponentInParent(); StartCoroutine(FadeSpeechBubble(1, 0, 0)); } private void Start() { Camera = GameObject.Find("FirstPerson_Camera").GetComponent(); } private void Update() { Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera); bool isSeen = GeometryUtility.TestPlanesAABB(planes, RootParentCollider.bounds) && Vector3.Distance(RootParentCollider.gameObject.transform.position, Camera.transform.position) < 10.0f; speechText.enabled = isSeen; bubbleImage.canvasRenderer.cull = !isSeen; } private void LateUpdate() { if (Player.Instance != null) transform.forward = Player.Instance.cameraController.playerCam.transform.forward; } public void DisplayMessage(string text) { if (IsCoroutineRunning) { // stop the coroutines if another messages is sent and restart them. StopCoroutine(messageCoroutine); StopCoroutine(fadeCoroutine); IsCoroutineRunning = false; } if (gameObject.activeInHierarchy) { fadeCoroutine = FadeSpeechBubble(0, 1, 0.75f); messageCoroutine = Co_DisplayMessage(text); StartCoroutine(messageCoroutine); StartCoroutine(fadeCoroutine); } } private IEnumerator Co_DisplayMessage(string text) { IsCoroutineRunning = true; speechText.text = text; speechText.ForceMeshUpdate(); int textLength = text.Length; if (textLength <= 10) { FullOpacityText = new WaitForSeconds(3f); } else if (textLength > 10 && textLength <= 20) { FullOpacityText = new WaitForSeconds(5.0f); } else if (textLength > 20 && textLength <= 40) { FullOpacityText = new WaitForSeconds(7.0f); } else { FullOpacityText = new WaitForSeconds(10.0f); } yield return FullOpacityText; StopCoroutine(fadeCoroutine); fadeCoroutine = FadeSpeechBubble(1, 0, fadeOutDuration); StartCoroutine(fadeCoroutine); yield return FadeDuration; IsCoroutineRunning = false; } private IEnumerator FadeSpeechBubble(float startAlpha, float endAlpha, float maxDuration) { float duration = 0; while (duration < 1) { canvasGroup.alpha = Mathf.Lerp(startAlpha, endAlpha, duration); duration += Time.deltaTime / maxDuration; yield return null; } canvasGroup.alpha = endAlpha; } }