- Добавлена система анимированных текстовых сплешей (TextSplash) с настройками масштаба, покачивания, движения и цвета - Добавлена поддержка циклического воспроизведения анимации сплешей - Добавлена настройка частоты покачивания для более плавной и непрерывной анимации - Добавлено отображение валюты в компоненте BalanceDisplay (берется из настройки payment.currency) - Добавлены поля для отображения номера поддержки и суперприза в главном меню - Добавлена возможность форматирования текстов через string.Format в MainMenu (supportNumberFormat, superPrizeFormat) - Валюта и тексты автоматически обновляются при изменении настроек
183 lines
6.3 KiB
C#
183 lines
6.3 KiB
C#
using TMPro;
|
||
using UnityEngine;
|
||
|
||
namespace RR.Common.UI
|
||
{
|
||
/// <summary>
|
||
/// Компонент для создания анимированного сплеша текста.
|
||
/// Поддерживает изменение размера, покачивание и изменение цвета.
|
||
/// </summary>
|
||
[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<TextMeshProUGUI>();
|
||
_rectTransform = GetComponent<RectTransform>();
|
||
_startPosition = _rectTransform.anchoredPosition;
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
StartAnimation();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Запускает анимацию сплеша
|
||
/// </summary>
|
||
public void StartAnimation()
|
||
{
|
||
_elapsed = 0f;
|
||
_isAnimating = true;
|
||
_startPosition = _rectTransform.anchoredPosition;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Устанавливает текст сплеша
|
||
/// </summary>
|
||
public void SetText(string text)
|
||
{
|
||
if (_textComponent != null)
|
||
{
|
||
_textComponent.text = text;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Устанавливает начальный цвет
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Устанавливает длительность анимации
|
||
/// </summary>
|
||
public void SetDuration(float duration)
|
||
{
|
||
animationDuration = duration;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Останавливает анимацию
|
||
/// </summary>
|
||
public void StopAnimation()
|
||
{
|
||
_isAnimating = false;
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
/// <summary>
|
||
/// Предварительный просмотр в редакторе
|
||
/// </summary>
|
||
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
|
||
}
|
||
}
|
||
|