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; } } }