90 lines
2.6 KiB
C#

using Cysharp.Threading.Tasks;
using System.Threading;
using TMPro;
using UnityEngine;
namespace RR.UI
{
public class CounterTMP : MonoBehaviour
{
[SerializeField] protected TextMeshProUGUI countLabel;
[Header("Настройки анимации")]
[SerializeField] private int scorePerSecond = 300;
[SerializeField] private float maxAnimationTime = 2;
[SerializeField] private string countFormat = "D4";
private CancellationTokenSource animationCts;
[field: SerializeField] public int Count { get; private set; }
public void Add(int value)
{
var oldCount = Count;
Count += value;
OnNewCount(oldCount, Count);
}
public void SetCount(int value)
{
var oldCount = Count;
Count = value;
OnNewCount(oldCount, Count);
}
public void ResetCount()
{
var oldCount = Count;
Count = 0;
OnNewCount(oldCount, Count);
}
protected virtual void OnNewCount(int oldCount, int newCount)
{
countLabel.text = newCount.ToString(countFormat);
if(scorePerSecond > 0)
{
AnimateScoreChange(oldCount, newCount).Forget();
}
}
public async UniTask AnimateScoreChange(int startScore, int endScore)
{
CancelAnimation();
animationCts = new();
int scoreDifference = endScore - startScore;
float animationTime = scoreDifference / scorePerSecond;
animationTime = Mathf.Clamp(animationTime, 0.1f, maxAnimationTime);
float elapsedTime = 0f;
while (elapsedTime < animationTime && !animationCts.Token.IsCancellationRequested)
{
await UniTask.Yield(animationCts.Token);
elapsedTime += Time.deltaTime;
float t = elapsedTime / animationTime;
t = Mathf.SmoothStep(0, 1, t);
int newScore = Mathf.RoundToInt(Mathf.Lerp(startScore, endScore, t));
countLabel.text = newScore.ToString("D4");
}
countLabel.text = endScore.ToString(countFormat);
}
private void CancelAnimation()
{
if (animationCts != null)
{
animationCts.Cancel();
animationCts.Dispose();
animationCts = null;
}
}
private void OnDestroy()
{
CancelAnimation();
}
}
}