using System.Collections;
using UnityEngine;
using UnityEngine.UI;
///
/// Компонент для плавного изменения значения Slider.
/// Вызывай метод AnimateTo() напрямую для анимации.
///
[RequireComponent(typeof(Slider))]
public class SmoothSlider : MonoBehaviour
{
[Header("Настройки плавности")]
[Tooltip("Длительность анимации в секундах")]
[SerializeField] private float duration = 0.3f;
[Tooltip("Кривая анимации (по умолчанию - плавная)")]
[SerializeField] private AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 1);
private Slider slider;
private Coroutine animationCoroutine;
private float targetValue;
private System.Action pendingCallback;
private int animationId; // Уникальный ID для отслеживания отмененных анимаций
private void Awake()
{
slider = GetComponent();
targetValue = slider.value;
animationId = 0;
}
///
/// Плавно анимирует слайдер к новому значению.
/// В конце анимации вызовет callback onComplete.
///
public void AnimateTo(float endValue, System.Action onComplete = null)
{
if (animationCoroutine != null)
{
StopCoroutine(animationCoroutine);
// ВАЖНО: Сохраняем СТАРОЕ целевое значение и callback ПЕРЕД обновлением
float previousTarget = targetValue;
System.Action previousCallback = pendingCallback;
// Устанавливаем финальное значение предыдущей анимации
slider.value = previousTarget;
// Вызываем callback с правильным финальным значением
previousCallback?.Invoke(previousTarget);
}
// Теперь обновляем на новые значения
targetValue = endValue;
pendingCallback = onComplete;
animationId++; // Новый ID для новой анимации
animationCoroutine = StartCoroutine(AnimateToValue(endValue, onComplete, animationId));
}
private IEnumerator AnimateToValue(float endValue, System.Action onComplete, int myAnimationId)
{
float startValue = slider.value;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
float t = Mathf.Clamp01(elapsed / duration);
slider.value = Mathf.Lerp(startValue, endValue, curve.Evaluate(t));
yield return null;
}
// Финальное значение - только если анимация не была отменена
if (myAnimationId == animationId)
{
slider.value = endValue;
targetValue = endValue;
onComplete?.Invoke(endValue);
animationCoroutine = null;
}
}
}