using TMPro;
using UnityEngine;
namespace RR.Common.UI
{
///
/// Компонент для создания анимированного сплеша текста.
/// Поддерживает изменение размера, покачивание и изменение цвета.
///
[RequireComponent(typeof(TextMeshProUGUI))]
public class TextSplash : MonoBehaviour
{
[Header("Настройки масштаба")]
[SerializeField] private bool animateScale = true;
[SerializeField] private AnimationCurve scaleCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
[SerializeField] private float startScale = 0.5f;
[SerializeField] private float endScale = 1.5f;
[Header("Настройки покачивания")]
[SerializeField] private bool animateSwing = true;
[SerializeField] private float swingAmplitude = 20f;
[SerializeField] private float swingFrequency = 2f;
[SerializeField] private AnimationCurve swingCurve = AnimationCurve.EaseInOut(0, 0, 0.5f, 1);
[Header("Настройки цвета")]
[SerializeField] private bool animateColor = true;
[SerializeField] private Gradient colorGradient = new Gradient();
[Header("Настройки движения")]
[SerializeField] private bool animateMovement = true;
[SerializeField] private Vector2 movementDirection = Vector2.up;
[SerializeField] private float movementDistance = 100f;
[SerializeField] private AnimationCurve movementCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
[Header("Общие настройки")]
[SerializeField] private float animationDuration = 1f;
[SerializeField] private bool loopAnimation = false;
[SerializeField] private bool destroyOnComplete = true;
private TextMeshProUGUI _textComponent;
private RectTransform _rectTransform;
private Vector2 _startPosition;
private float _elapsed;
private bool _isAnimating;
private void Awake()
{
_textComponent = GetComponent();
_rectTransform = GetComponent();
_startPosition = _rectTransform.anchoredPosition;
}
private void OnEnable()
{
StartAnimation();
}
///
/// Запускает анимацию сплеша
///
public void StartAnimation()
{
_elapsed = 0f;
_isAnimating = true;
_startPosition = _rectTransform.anchoredPosition;
}
///
/// Устанавливает текст сплеша
///
public void SetText(string text)
{
if (_textComponent != null)
{
_textComponent.text = text;
}
}
///
/// Устанавливает начальный цвет
///
public void SetColor(Color color)
{
if (_textComponent != null)
{
_textComponent.color = color;
}
}
private void Update()
{
if (!_isAnimating) return;
_elapsed += Time.unscaledDeltaTime;
float t = Mathf.Clamp01(_elapsed / animationDuration);
// Анимация масштаба
if (animateScale)
{
float scaleValue = Mathf.Lerp(startScale, endScale, scaleCurve.Evaluate(t));
_rectTransform.localScale = Vector3.one * scaleValue;
}
// Анимация покачивания (rotation)
if (animateSwing)
{
float swingValue = swingCurve.Evaluate(t) * swingAmplitude;
// Используем частоту для создания непрерывного покачивания
float swingAngle = Mathf.Sin(t * Mathf.PI * 2 * swingFrequency) * swingValue;
_rectTransform.localRotation = Quaternion.Euler(0, 0, swingAngle);
}
// Анимация движения
if (animateMovement)
{
float moveValue = movementCurve.Evaluate(t) * movementDistance;
Vector2 offset = movementDirection.normalized * moveValue;
_rectTransform.anchoredPosition = _startPosition + offset;
}
// Анимация цвета
if (animateColor && _textComponent != null)
{
_textComponent.color = colorGradient.Evaluate(t);
}
// Завершение анимации
if (t >= 1f)
{
if (loopAnimation)
{
// Перезапускаем анимацию с начала
_elapsed = 0f;
}
else
{
_isAnimating = false;
if (destroyOnComplete)
{
Destroy(gameObject);
}
}
}
}
///
/// Устанавливает длительность анимации
///
public void SetDuration(float duration)
{
animationDuration = duration;
}
///
/// Останавливает анимацию
///
public void StopAnimation()
{
_isAnimating = false;
}
#if UNITY_EDITOR
///
/// Предварительный просмотр в редакторе
///
private void OnValidate()
{
if (colorGradient == null || colorGradient.colorKeys.Length == 0)
{
// Устанавливаем градиент по умолчанию (белый -> прозрачный)
colorGradient = new Gradient();
colorGradient.SetKeys(
new[] { new GradientColorKey(Color.white, 0f), new GradientColorKey(Color.white, 1f) },
new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(0f, 1f) }
);
}
}
#endif
}
}