using System; using System.Collections; using System.Collections.Generic; using System.Linq; using DG.Tweening; using LuaInterface; using UnityEngine; using UnityEngine.UI; public class RollingNumberText : MonoBehaviour { [SerializeField] [Tooltip("按最高位起始顺序设置每位数字Text(显示组)")] private List _numbers; [SerializeField] [Tooltip("按最高位起始顺序设置每位数字Text(替换组)")] private List _unactiveNumbers; /// /// 动画时长 /// [SerializeField] private float _duration = 1.5f; [SerializeField] private float stayTime = 0.5f; /// /// 数字每次滚动时长 /// [SerializeField] private float _rollingDuration = 0.05f; /// /// 数字每次变动数值 /// private int _speed; /// /// 滚动延迟(每进一位增加一倍延迟,让滚动看起来更随机自然) /// [SerializeField] private float _delay = 0.008f; /// /// Text文字宽高 /// private Vector2 _numberSize; /// /// 当前数字 /// private int _curNumber; /// /// 起始数字 /// private int _fromNumber; /// /// 最终数字 /// private int _toNumber; /// /// 各位数字的缓动实例 /// private List _tweener = new List(); /// /// 是否处于数字滚动中 /// private bool _isJumping; /// /// 滚动完毕回调 /// public Action OnComplete; public bool needOver = true; [NoToLua] private void Awake() { if (_numbers.Count == 0 || _unactiveNumbers.Count == 0) { DebugHelper.LogError("[RollingNumberText] 还未设置Text组件!"); return; } _numberSize = _numbers[0].rectTransform.sizeDelta; } [NoToLua] public float duration { get { return _duration; } set { _duration = value; } } private float _different; [NoToLua] public float different { get { return _different; } } public void Change(int from, int to) { Debug.Log(from + " " + to); bool isRepeatCall = _isJumping && _fromNumber == from && _toNumber == to; if (isRepeatCall) return; bool isContinuousChange = (_toNumber == from) && ((to - from > 0 && _different > 0) || (to - from < 0 && _different < 0)); if (_isJumping && isContinuousChange) { } else { _fromNumber = from; _curNumber = _fromNumber; } _toNumber = to; _different = _toNumber - _fromNumber; _speed = (int)Math.Ceiling(_different / (_duration * (1 / _rollingDuration))); _speed = _speed == 0 ? (_different > 0 ? 1 : -1) : _speed; SetNumber(_curNumber, false); _isJumping = true; needOver = true; StopCoroutine("DoJumpNumber"); StartCoroutine("DoJumpNumber"); } [NoToLua] public int number { get { return _toNumber; } set { if (_toNumber == value) return; Change(_curNumber, _toNumber); } } [NoToLua] IEnumerator DoJumpNumber() { while (needOver) { if (_speed > 0)//增加 { _curNumber = Math.Min(_curNumber + _speed, _toNumber); } else if (_speed < 0) //减少 { _curNumber = Math.Max(_curNumber + _speed, _toNumber); } SetNumber(_curNumber, true); if (_curNumber == _toNumber) { yield return new WaitForSeconds(stayTime); StopCoroutine("DoJumpNumber"); _isJumping = false; needOver = false; if (OnComplete != null) OnComplete(); yield return null; } yield return new WaitForSeconds(_rollingDuration); } } [NoToLua] /// /// 设置战力数字 /// /// /// public void SetNumber(int v, bool isTween) { char[] c = v.ToString().ToCharArray(); Array.Reverse(c); string s = new string(c); if (!isTween) { for (int i = 0; i < _numbers.Count; i++) { if (i < s.Count()) _numbers[i].text = s[i] + ""; else _numbers[i].text = "0"; _numbers[i].gameObject.SetActive(i < s.Count()); } } else { while (_tweener.Count > 0) { _tweener[0].Complete(); _tweener.RemoveAt(0); } for (int i = 0; i < _numbers.Count; i++) { if (i < s.Count()) { _unactiveNumbers[i].text = s[i] + ""; } else { _unactiveNumbers[i].text = "0"; } _unactiveNumbers[i].gameObject.SetActive(i < s.Count()); _unactiveNumbers[i].rectTransform.anchoredPosition = new Vector2(_unactiveNumbers[i].rectTransform.anchoredPosition.x, (_speed > 0 ? -1 : 1) * _numberSize.y); _numbers[i].rectTransform.anchoredPosition = new Vector2(_unactiveNumbers[i].rectTransform.anchoredPosition.x, 0); if (_unactiveNumbers[i].text != _numbers[i].text) { DoTween(_numbers[i], (_speed > 0 ? 1 : -1) * _numberSize.y, _delay * i); DoTween(_unactiveNumbers[i], 0, _delay * i); Text tmp = _numbers[i]; _numbers[i] = _unactiveNumbers[i]; _unactiveNumbers[i] = tmp; } } } } [NoToLua] public void DoTween(Text text, float endValue, float delay) { DG.Tweening.Tweener t = DOTween.To(() => text.rectTransform.anchoredPosition, (x) => { text.rectTransform.anchoredPosition = x; }, new Vector2(text.rectTransform.anchoredPosition.x, endValue), _rollingDuration - delay).SetDelay(delay); _tweener.Add(t); } [NoToLua] [ContextMenu("测试数字变化")] public void TestChange() { Change(UnityEngine.Random.Range(1, 1), UnityEngine.Random.Range(1, 100000)); } public void RollingNumberOver(int from, int to) { //bool isRepeatCall = _isJumping && _fromNumber == from && _toNumber == to; //if (isRepeatCall) return; StopCoroutine("DoJumpNumber"); _isJumping = false; needOver = false; } }