using System.Collections; using TMPro; using UnityEngine; using UnityEngine.UI; public class DrawVisual : MonoBehaviour { [Header("Refs")] [SerializeField] private Image panel; //[SerializeField] private Image lamp; [SerializeField] private TextMeshProUGUI maintext; [Header("Speeds")] [SerializeField] private float curtainSpeed = 3f; // скорость изменения высоты [SerializeField] private float scaleSpeed = 3f; // скорость изменения масштаба текста [SerializeField] private float blinkFreq = 2f; // герцы мерцания private void Start() { Hide(); } public void Show() { StopAllCoroutines(); // гасим всё, что крутилось до этого StartCoroutine(OpenAnimation()); // последовательная анимация StartCoroutine(Blink(maintext, 0.4f, 1f)); //StartCoroutine(Blink(lamp, 0.4f, 1f)); } public void Hide() { StopAllCoroutines(); StartCoroutine(CloseAnimation()); // обратный порядок StartCoroutine(Blink(maintext, 0.4f, 1f)); //StartCoroutine(Blink(lamp, 0.4f, 1f)); } // ===== Sequences ===== IEnumerator OpenAnimation() { // Сначала шторка, потом текст yield return SetCurtainHeight(2.7f, curtainSpeed); yield return SetTextScale(1f, scaleSpeed); } IEnumerator CloseAnimation() { // Обратный порядок: сначала текст схлопывается, потом шторка yield return SetTextScale(0f, scaleSpeed); yield return SetCurtainHeight(0f, curtainSpeed); } // ===== Anim pieces ===== // Шторка: меняем визуальную высоту (учитывает anchors) IEnumerator SetCurtainHeight(float targetHeight, float speed) { var rt = panel.rectTransform; const float EPS = 0.01f; // Берём текущее визуальное значение, а не sizeDelta (надёжнее при разных якорях) while (Mathf.Abs(rt.rect.height - targetHeight) > EPS) { float current = rt.rect.height; float next = Mathf.MoveTowards(current, targetHeight, speed * Time.deltaTime); rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, next); yield return null; } // Финальное выравнивание rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, targetHeight); } // Текст: масштаб только по Y (оставляем X/Z как есть) IEnumerator SetTextScale(float targetScaleY, float speed) { var rt = maintext.rectTransform; const float EPS = 0.001f; while (Mathf.Abs(rt.localScale.y - targetScaleY) > EPS) { float y = Mathf.MoveTowards(rt.localScale.y, targetScaleY, speed * Time.deltaTime); rt.localScale = new Vector3(rt.localScale.x, y, rt.localScale.z); yield return null; } rt.localScale = new Vector3(rt.localScale.x, targetScaleY, rt.localScale.z); } // Бесконечное мерцание альфы между min и max IEnumerator Blink(MaskableGraphic graphic, float minAlpha, float maxAlpha) { // Нормализация входа minAlpha = Mathf.Clamp01(minAlpha); maxAlpha = Mathf.Clamp01(maxAlpha); if (maxAlpha < minAlpha) (minAlpha, maxAlpha) = (maxAlpha, minAlpha); float amplitude = maxAlpha - minAlpha; // раньше было max - max → 0 (баг) while (true) { Color c = graphic.color; // Используем unscaledTime, чтобы мерцание не зависело от Time.timeScale c.a = minAlpha + Mathf.PingPong(Time.time * blinkFreq, amplitude); graphic.color = c; yield return null; } } }