sea-battle/Assets/Scripts/UI/SmoothSlider.cs
2026-01-09 08:45:22 +03:00

86 lines
2.7 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Êîìïîíåíò äëÿ ïëàâíîãî èçìåíåíèÿ çíà÷åíèÿ Slider.
/// Âûçûâàé ìåòîä AnimateTo() íàïðÿìóþ äëÿ àíèìàöèè.
/// </summary>
[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<float> pendingCallback;
private int animationId; // Óíèêàëüíûé ID äëÿ îòñëåæèâàíèÿ îòìåíåííûõ àíèìàöèé
private void Awake()
{
slider = GetComponent<Slider>();
targetValue = slider.value;
animationId = 0;
}
/// <summary>
/// Ïëàâíî àíèìèðóåò ñëàéäåð ê íîâîìó çíà÷åíèþ.
/// Â êîíöå àíèìàöèè âûçîâåò callback onComplete.
/// </summary>
public void AnimateTo(float endValue, System.Action<float> onComplete = null)
{
if (animationCoroutine != null)
{
StopCoroutine(animationCoroutine);
// ÂÀÆÍÎ: Ñîõðàíÿåì ÑÒÀÐÎÅ öåëåâîå çíà÷åíèå è callback ÏÅÐÅÄ îáíîâëåíèåì
float previousTarget = targetValue;
System.Action<float> 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<float> 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;
}
}
}