qiuqiu 5 hónapja
szülő
commit
301332e0e6

+ 14 - 10
.idea/workspace.xml

@@ -7,7 +7,10 @@
   </component>
   <component name="ChangeListManager">
     <list default="true" id="fec10672-acda-4616-894b-a4b6f93aea6f" name="Default Changelist" comment="">
-      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/笔记文件/2.笔记/unity动画序列帧代码实现 代码缓存.md" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/笔记文件/2.笔记/unity动画序列帧代码实现 代码缓存_第一章.md" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/笔记文件/2.笔记/unity动画序列帧代码实现 代码缓存_第二章.md" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/笔记文件/日记/2025_07_10_星期四.md" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -90,13 +93,7 @@
       <workItem from="1751590939949" duration="1461000" />
       <workItem from="1751866574639" duration="1253000" />
       <workItem from="1751936564646" duration="1228000" />
-    </task>
-    <task id="LOCAL-00004" summary="测试提交">
-      <created>1742958527917</created>
-      <option name="number" value="00004" />
-      <option name="presentableId" value="LOCAL-00004" />
-      <option name="project" value="LOCAL" />
-      <updated>1742958527917</updated>
+      <workItem from="1752110404666" duration="1217000" />
     </task>
     <task id="LOCAL-00005" summary="测试提交">
       <created>1742960760863</created>
@@ -434,7 +431,14 @@
       <option name="project" value="LOCAL" />
       <updated>1752033448623</updated>
     </task>
-    <option name="localTasksCounter" value="53" />
+    <task id="LOCAL-00053" summary="提交">
+      <created>1752126318124</created>
+      <option name="number" value="00053" />
+      <option name="presentableId" value="LOCAL-00053" />
+      <option name="project" value="LOCAL" />
+      <updated>1752126318125</updated>
+    </task>
+    <option name="localTasksCounter" value="54" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -451,7 +455,7 @@
                   <entry key="branch">
                     <value>
                       <list>
-                        <option value="main" />
+                        <option value="origin/main" />
                       </list>
                     </value>
                   </entry>

+ 7 - 0
笔记文件/2.笔记/unity数字text滚动代码实现 代码缓存.md

@@ -0,0 +1,7 @@
+#unity/日常积累 
+
+[[unity数字text滚动代码实现 代码缓存_第一章|第一章]]
+
+[[unity数字text滚动代码实现 代码缓存_第二章|第二章]]
+
+[[unity数字text滚动代码实现 代码缓存_第三章|第三章]]

+ 968 - 0
笔记文件/2.笔记/unity数字text滚动代码实现 代码缓存_第一章.md

@@ -0,0 +1,968 @@
+## NumberRollAnimation
+
+``` cs
+using System;
+using System.Collections;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace SlotGame
+{
+    /// <summary>
+    /// 数字滚动动画组件 - 用于显示数字增加的滚动效果
+    /// Number rolling animation component - for displaying number increment rolling effects
+    /// </summary>
+    public class NumberRollAnimation : MonoBehaviour
+    {
+        [Header("目标组件 Target Components")]
+        [SerializeField] private Text uiText;
+        
+        [Header("动画设置 Animation Settings")]
+        [SerializeField] private float rollDuration = 2f;
+        [SerializeField] private AnimationCurve rollCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
+        [SerializeField] private bool useRandomRolling = true;
+        [SerializeField] private float randomRollSpeed = 0.05f;
+        
+        [Header("大数字优化 Large Number Optimization")]
+        [SerializeField] private bool enableLargeNumberMode = true;
+        [SerializeField] private long largeNumberThreshold = 1000000; // 100万以上算大数字
+        [SerializeField] private float largeNumberDurationMultiplier = 1.5f; // 大数字动画时长倍数
+        [SerializeField] private float ultraLargeNumberThreshold = 100000000; // 1亿以上算超大数字
+        [SerializeField] private float ultraLargeNumberDurationMultiplier = 2.0f; // 超大数字动画时长倍数
+        [SerializeField] private int largeNumberUpdateInterval = 2; // 大数字更新间隔帧数(优化性能)
+        
+        [Header("数字格式 Number Format")]
+        [SerializeField] private string numberFormat = "N0"; // N0 = 1,234,567
+        [SerializeField] private bool useCustomFormat = false;
+        [SerializeField] private string customFormat = "{0:N0}";
+        
+        [Header("滚动效果 Rolling Effects")]
+        [SerializeField] private bool enableSound = true;
+        [SerializeField] private AudioClip rollSound;
+        [SerializeField] private AudioClip completeSound;
+        [SerializeField] private bool enableShake = false;
+        [SerializeField] private float shakeIntensity = 2f;
+        
+        [Header("调试 Debug")]
+        [SerializeField] private bool debugMode = false;
+        
+        // 私有变量
+        private long currentValue;
+        private long targetValue;
+        private bool isRolling = false;
+        private Coroutine rollCoroutine;
+        private AudioSource audioSource;
+        private Vector3 originalPosition;
+        private int frameCounter = 0; // 用于大数字性能优化
+        
+        // 事件
+        public event Action<long> OnValueChanged;
+        public event Action<long> OnRollComplete;
+        public event Action OnRollStart;
+        
+        #region Unity生命周期
+        
+        private void Awake()
+        {
+            InitializeComponents();
+        }
+        
+        private void Start()
+        {
+            originalPosition = transform.localPosition;
+        }
+        
+        #endregion
+        
+        #region 初始化
+        
+        private void InitializeComponents()
+        {
+            // 自动获取文本组件
+            if (uiText == null) uiText = GetComponent<Text>();
+            
+            // 获取或创建AudioSource
+            audioSource = GetComponent<AudioSource>();
+            if (audioSource == null && enableSound)
+            {
+                audioSource = gameObject.AddComponent<AudioSource>();
+                audioSource.playOnAwake = false;
+            }
+        }
+        
+        #endregion
+        
+        #region 公共方法
+        
+        /// <summary>
+        /// 设置当前值(无动画)
+        /// </summary>
+        public void SetValue(long value)
+        {
+            currentValue = value;
+            targetValue = value;
+            UpdateDisplayText(value);
+            
+            if (debugMode) Debug.Log($"NumberRoll: Set value to {value}");
+        }
+        
+        /// <summary>
+        /// 滚动到目标值
+        /// </summary>
+        public void RollToValue(long targetValue, float? customDuration = null)
+        {
+            if (isRolling)
+            {
+                StopRoll();
+            }
+            
+            this.targetValue = targetValue;
+            float duration = customDuration ?? CalculateOptimalDuration(currentValue, targetValue);
+            
+            rollCoroutine = StartCoroutine(RollCoroutine(currentValue, targetValue, duration));
+            
+            if (debugMode) Debug.Log($"NumberRoll: Rolling from {currentValue} to {targetValue} in {duration}s");
+        }
+        
+        /// <summary>
+        /// 增加值(从当前值滚动增加)
+        /// </summary>
+        public void AddValue(long addAmount, float? customDuration = null)
+        {
+            long newTarget = currentValue + addAmount;
+            RollToValue(newTarget, customDuration);
+        }
+        
+        /// <summary>
+        /// 停止滚动
+        /// </summary>
+        public void StopRoll()
+        {
+            if (rollCoroutine != null)
+            {
+                StopCoroutine(rollCoroutine);
+                rollCoroutine = null;
+            }
+            
+            isRolling = false;
+            currentValue = targetValue;
+            UpdateDisplayText(currentValue);
+            
+            // 重置位置
+            if (enableShake)
+            {
+                transform.localPosition = originalPosition;
+            }
+        }
+        
+        /// <summary>
+        /// 立即完成滚动
+        /// </summary>
+        public void CompleteRoll()
+        {
+            StopRoll();
+            OnRollComplete?.Invoke(currentValue);
+        }
+        
+        #endregion
+        
+        #region 大数字优化方法
+        
+        /// <summary>
+        /// 根据数字大小计算最佳动画时长
+        /// </summary>
+        private float CalculateOptimalDuration(long startValue, long endValue)
+        {
+            if (!enableLargeNumberMode)
+                return rollDuration;
+            
+            long difference = Math.Abs(endValue - startValue);
+            
+            if (difference >= ultraLargeNumberThreshold)
+            {
+                // 超大数字:1亿以上
+                return rollDuration * ultraLargeNumberDurationMultiplier;
+            }
+            else if (difference >= largeNumberThreshold)
+            {
+                // 大数字:100万以上
+                return rollDuration * largeNumberDurationMultiplier;
+            }
+            else
+            {
+                // 普通数字
+                return rollDuration;
+            }
+        }
+        
+        /// <summary>
+        /// 检查是否为大数字
+        /// </summary>
+        private bool IsLargeNumber(long value)
+        {
+            return enableLargeNumberMode && Math.Abs(value) >= largeNumberThreshold;
+        }
+        
+        /// <summary>
+        /// 检查是否需要跳帧优化(大数字性能优化)
+        /// </summary>
+        private bool ShouldSkipFrame()
+        {
+            if (!IsLargeNumber(targetValue))
+                return false;
+                
+            frameCounter++;
+            if (frameCounter >= largeNumberUpdateInterval)
+            {
+                frameCounter = 0;
+                return false;
+            }
+            return true;
+        }
+        
+        #endregion
+        
+        #region 滚动逻辑
+        
+        private IEnumerator RollCoroutine(long startValue, long endValue, float duration)
+        {
+            isRolling = true;
+            frameCounter = 0;
+            OnRollStart?.Invoke();
+            
+            // 播放滚动音效
+            if (enableSound && rollSound != null && audioSource != null)
+            {
+                audioSource.clip = rollSound;
+                audioSource.loop = true;
+                audioSource.Play();
+            }
+            
+            float elapsedTime = 0f;
+            long difference = endValue - startValue;
+            bool isLargeNum = IsLargeNumber(endValue);
+            
+            // 大数字使用不同的随机策略
+            float randomIntensity = isLargeNum ? 0.05f : 0.1f; // 大数字减少随机波动
+            float randomPhase = isLargeNum ? 0.9f : 0.8f; // 大数字延长随机阶段
+            
+            if (debugMode && isLargeNum) 
+                Debug.Log($"NumberRoll: Large number detected, using optimized animation for {endValue}");
+            
+            while (elapsedTime < duration)
+            {
+                elapsedTime += Time.deltaTime;
+                float progress = elapsedTime / duration;
+                float curveProgress = rollCurve.Evaluate(progress);
+                
+                // 计算当前值
+                long rollingValue;
+                if (useRandomRolling && progress < randomPhase)
+                {
+                    rollingValue = startValue + (long)(difference * curveProgress);
+                    // 大数字优化:减少随机波动强度,增加波动频率控制
+                    if (Time.time % randomRollSpeed < Time.deltaTime)
+                    {
+                        long randomOffset = (long)(difference * randomIntensity * UnityEngine.Random.Range(-1f, 1f));
+                        rollingValue += randomOffset;
+                    }
+                }
+                else
+                {
+                    rollingValue = startValue + (long)(difference * curveProgress);
+                }
+                
+                currentValue = rollingValue;
+                
+                // 大数字性能优化:跳帧更新
+                if (!ShouldSkipFrame())
+                {
+                    UpdateDisplayText(currentValue);
+                    OnValueChanged?.Invoke(currentValue);
+                }
+                
+                // 震动效果
+                if (enableShake)
+                {
+                    float shakeAmount = shakeIntensity * (1f - progress);
+                    // 大数字减少震动强度
+                    if (isLargeNum) shakeAmount *= 0.5f;
+                    
+                    Vector3 shakeOffset = new Vector3(
+                        UnityEngine.Random.Range(-shakeAmount, shakeAmount),
+                        UnityEngine.Random.Range(-shakeAmount, shakeAmount),
+                        0f
+                    );
+                    transform.localPosition = originalPosition + shakeOffset;
+                }
+                
+                yield return null;
+            }
+            
+            // 确保最终值正确
+            currentValue = endValue;
+            UpdateDisplayText(currentValue);
+            
+            // 重置位置
+            if (enableShake)
+            {
+                transform.localPosition = originalPosition;
+            }
+            
+            // 停止滚动音效,播放完成音效
+            if (enableSound && audioSource != null)
+            {
+                audioSource.Stop();
+                if (completeSound != null)
+                {
+                    audioSource.PlayOneShot(completeSound);
+                }
+            }
+            
+            isRolling = false;
+            rollCoroutine = null;
+            
+            OnValueChanged?.Invoke(currentValue);
+            OnRollComplete?.Invoke(currentValue);
+            
+            if (debugMode) Debug.Log($"NumberRoll: Completed rolling to {currentValue}");
+        }
+        
+        #endregion
+        
+        #region 文本更新
+        
+        private void UpdateDisplayText(long value)
+        {
+            string formattedText = FormatNumber(value);
+            
+            if (uiText != null)
+                uiText.text = formattedText;
+        }
+        
+        private string FormatNumber(long value)
+        {
+            if (useCustomFormat)
+            {
+                return string.Format(customFormat, value);
+            }
+            else
+            {
+                return value.ToString(numberFormat);
+            }
+        }
+        
+        #endregion
+        
+        #region 属性访问器
+        
+        public long CurrentValue => currentValue;
+        public long TargetValue => targetValue;
+        public bool IsRolling => isRolling;
+        
+        public float RollDuration
+        {
+            get => rollDuration;
+            set => rollDuration = Mathf.Max(0.1f, value);
+        }
+        
+        /// <summary>
+        /// 获取当前是否为大数字模式
+        /// </summary>
+        public bool IsInLargeNumberMode => IsLargeNumber(currentValue) || IsLargeNumber(targetValue);
+        
+        #endregion
+        
+        #region 调试方法
+        
+        [ContextMenu("Test Roll +1000")]
+        private void TestRoll1000()
+        {
+            AddValue(1000);
+        }
+        
+        [ContextMenu("Test Roll +10000")]
+        private void TestRoll10000()
+        {
+            AddValue(10000);
+        }
+        
+        [ContextMenu("Test Set 1000000")]
+        private void TestSetMillion()
+        {
+            SetValue(1000000);
+        }
+        
+        [ContextMenu("Test Large Number +10000000")]
+        private void TestLargeNumber()
+        {
+            AddValue(10000000); // 1千万
+        }
+        
+        [ContextMenu("Test Ultra Large Number +100000000")]
+        private void TestUltraLargeNumber()
+        {
+            AddValue(100000000); // 1亿
+        }
+        
+        [ContextMenu("Test Jackpot Size")]
+        private void TestJackpotSize()
+        {
+            RollToValue(999999999); // 接近10亿
+        }
+        
+        #endregion
+    }
+} 
+```
+
+## NumberRollExample
+
+``` cs
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace SlotGame
+{
+    /// <summary>
+    /// 数字滚动动画使用示例
+    /// Number roll animation usage examples
+    /// </summary>
+    public class NumberRollExample : MonoBehaviour
+    {
+        [Header("数字滚动组件引用 Number Roll References")]
+        [SerializeField] private NumberRollAnimation scoreRoll;
+        [SerializeField] private NumberRollAnimation jackpotRoll;
+        [SerializeField] private NumberRollAnimation winAmountRoll;
+        [SerializeField] private NumberRollAnimation balanceRoll;
+        
+        [Header("翻页数字组件引用 Flip Number References")]
+        [SerializeField] private FlipNumberDisplay megaJackpotFlip;
+        [SerializeField] private FlipNumberDisplay ultraWinFlip;
+        
+        [Header("测试按钮 Test Buttons")]
+        [SerializeField] private Button addScoreBtn;
+        [SerializeField] private Button addJackpotBtn;
+        [SerializeField] private Button showWinBtn;
+        [SerializeField] private Button updateBalanceBtn;
+        
+        [Header("大数字测试按钮 Large Number Test Buttons")]
+        [SerializeField] private Button largeWinBtn;
+        [SerializeField] private Button megaJackpotBtn;
+        [SerializeField] private Button ultraWinBtn;
+        [SerializeField] private Button resetAllBtn;
+        
+        [Header("测试数值 Test Values")]
+        [SerializeField] private long scoreIncrement = 1000;
+        [SerializeField] private long jackpotIncrement = 50000;
+        [SerializeField] private long winAmount = 25000;
+        [SerializeField] private long balanceAmount = 100000;
+        
+        [Header("大数字测试数值 Large Number Test Values")]
+        [SerializeField] private long largeWinAmount = 50000000; // 5千万
+        [SerializeField] private long megaJackpotAmount = 500000000; // 5亿
+        [SerializeField] private long ultraWinAmount = 999999999999; // 接近万亿
+        
+        private void Start()
+        {
+            InitializeUI();
+            RegisterEvents();
+        }
+        
+        private void OnDestroy()
+        {
+            UnregisterEvents();
+        }
+        
+        #region 初始化
+        
+        private void InitializeUI()
+        {
+            // 设置初始值
+            if (scoreRoll != null)
+                scoreRoll.SetValue(0);
+            
+            if (jackpotRoll != null)
+                jackpotRoll.SetValue(3000000); // 初始奖池
+            
+            if (winAmountRoll != null)
+                winAmountRoll.SetValue(0);
+            
+            if (balanceRoll != null)
+                balanceRoll.SetValue(50000); // 初始余额
+            
+            // 设置大数字显示初始值
+            if (megaJackpotFlip != null)
+                megaJackpotFlip.SetValue(1000000000); // 10亿起始奖池
+            
+            if (ultraWinFlip != null)
+                ultraWinFlip.SetValue(0);
+        }
+        
+        private void RegisterEvents()
+        {
+            // 按钮事件
+            if (addScoreBtn != null)
+                addScoreBtn.onClick.AddListener(OnAddScore);
+            
+            if (addJackpotBtn != null)
+                addJackpotBtn.onClick.AddListener(OnAddJackpot);
+            
+            if (showWinBtn != null)
+                showWinBtn.onClick.AddListener(OnShowWin);
+            
+            if (updateBalanceBtn != null)
+                updateBalanceBtn.onClick.AddListener(OnUpdateBalance);
+            
+            // 大数字测试按钮事件
+            if (largeWinBtn != null)
+                largeWinBtn.onClick.AddListener(OnLargeWin);
+            
+            if (megaJackpotBtn != null)
+                megaJackpotBtn.onClick.AddListener(OnMegaJackpot);
+            
+            if (ultraWinBtn != null)
+                ultraWinBtn.onClick.AddListener(OnUltraWin);
+            
+            if (resetAllBtn != null)
+                resetAllBtn.onClick.AddListener(OnResetAll);
+            
+            // 数字滚动事件
+            if (scoreRoll != null)
+            {
+                scoreRoll.OnRollStart += () => Debug.Log("Score rolling started");
+                scoreRoll.OnRollComplete += (value) => Debug.Log($"Score rolling completed: {value:N0}");
+            }
+            
+            if (winAmountRoll != null)
+            {
+                winAmountRoll.OnRollComplete += OnWinRollComplete;
+            }
+            
+            // 大数字组件事件
+            if (megaJackpotFlip != null)
+            {
+                megaJackpotFlip.OnLargeNumberDetected += (value) => Debug.Log($"Mega Jackpot: Large number detected! {value:N0}");
+                megaJackpotFlip.OnSpinComplete += (value) => Debug.Log($"Mega Jackpot spin completed: {value:N0}");
+            }
+            
+            if (ultraWinFlip != null)
+            {
+                ultraWinFlip.OnLargeNumberDetected += (value) => Debug.Log($"Ultra Win: Large number detected! {value:N0}");
+                ultraWinFlip.OnSpinComplete += OnUltraWinComplete;
+            }
+        }
+        
+        private void UnregisterEvents()
+        {
+            if (addScoreBtn != null)
+                addScoreBtn.onClick.RemoveListener(OnAddScore);
+            
+            if (addJackpotBtn != null)
+                addJackpotBtn.onClick.RemoveListener(OnAddJackpot);
+            
+            if (showWinBtn != null)
+                showWinBtn.onClick.RemoveListener(OnShowWin);
+            
+            if (updateBalanceBtn != null)
+                updateBalanceBtn.onClick.RemoveListener(OnUpdateBalance);
+            
+            // 移除大数字测试按钮事件
+            if (largeWinBtn != null)
+                largeWinBtn.onClick.RemoveListener(OnLargeWin);
+            
+            if (megaJackpotBtn != null)
+                megaJackpotBtn.onClick.RemoveListener(OnMegaJackpot);
+            
+            if (ultraWinBtn != null)
+                ultraWinBtn.onClick.RemoveListener(OnUltraWin);
+            
+            if (resetAllBtn != null)
+                resetAllBtn.onClick.RemoveListener(OnResetAll);
+        }
+        
+        #endregion
+        
+        #region 按钮事件处理
+        
+        private void OnAddScore()
+        {
+            if (scoreRoll != null)
+            {
+                scoreRoll.AddValue(scoreIncrement, 1.5f); // 1.5秒滚动时间
+            }
+        }
+        
+        private void OnAddJackpot()
+        {
+            if (jackpotRoll != null)
+            {
+                jackpotRoll.AddValue(jackpotIncrement, 2f); // 2秒滚动时间
+            }
+        }
+        
+        private void OnShowWin()
+        {
+            if (winAmountRoll != null)
+            {
+                // 先重置为0,然后滚动到中奖金额
+                winAmountRoll.SetValue(0);
+                winAmountRoll.RollToValue(winAmount, 3f); // 3秒展示中奖动画
+            }
+        }
+        
+        private void OnUpdateBalance()
+        {
+            if (balanceRoll != null)
+            {
+                balanceRoll.RollToValue(balanceAmount, 1f);
+            }
+        }
+        
+        #endregion
+        
+        #region 大数字测试事件处理
+        
+        private void OnLargeWin()
+        {
+            Debug.Log($"Testing Large Win: {largeWinAmount:N0}");
+            
+            // 使用NumberRollAnimation显示大奖
+            if (winAmountRoll != null)
+            {
+                winAmountRoll.SetValue(0);
+                winAmountRoll.RollToValue(largeWinAmount); // 自动使用大数字优化
+            }
+            
+            // 同时更新分数(演示大数字性能优化)
+            if (scoreRoll != null)
+            {
+                StartCoroutine(DelayedScoreUpdate(largeWinAmount, 4f));
+            }
+        }
+        
+        private void OnMegaJackpot()
+        {
+            Debug.Log($"Testing Mega Jackpot: {megaJackpotAmount:N0}");
+            
+            // 使用FlipNumberDisplay显示超级大奖
+            if (megaJackpotFlip != null)
+            {
+                megaJackpotFlip.SpinToValue(megaJackpotAmount); // 自动使用Level 2优化
+            }
+            
+            // 同时播放特效提示
+            ShowMegaJackpotEffect();
+        }
+        
+        private void OnUltraWin()
+        {
+            Debug.Log($"Testing Ultra Win: {ultraWinAmount:N0}");
+            
+            // 使用FlipNumberDisplay显示终极大奖
+            if (ultraWinFlip != null)
+            {
+                ultraWinFlip.SetValue(0);
+                ultraWinFlip.SpinToValue(ultraWinAmount); // 自动使用Level 3优化
+            }
+            
+            // 触发终极大奖序列
+            StartCoroutine(UltraWinSequence());
+        }
+        
+        private void OnResetAll()
+        {
+            Debug.Log("Resetting all displays to initial values");
+            
+            // 重置所有数字显示
+            if (scoreRoll != null) scoreRoll.SetValue(0);
+            if (jackpotRoll != null) jackpotRoll.SetValue(3000000);
+            if (winAmountRoll != null) winAmountRoll.SetValue(0);
+            if (balanceRoll != null) balanceRoll.SetValue(50000);
+            
+            if (megaJackpotFlip != null) megaJackpotFlip.SetValue(1000000000);
+            if (ultraWinFlip != null) ultraWinFlip.SetValue(0);
+        }
+        
+        #endregion
+        
+        #region 大数字特效和序列
+        
+        private void ShowMegaJackpotEffect()
+        {
+            // 可以在这里添加粒子特效、屏幕震动等
+            Debug.Log("🎉 MEGA JACKPOT EFFECT! 🎉");
+            
+            // 演示颜色变化效果
+            if (megaJackpotFlip != null)
+            {
+                megaJackpotFlip.SetLargeNumberColorEffect(Color.white, Color.yellow);
+            }
+        }
+        
+        private System.Collections.IEnumerator UltraWinSequence()
+        {
+            Debug.Log("🌟 ULTRA WIN SEQUENCE STARTED! 🌟");
+            
+            // 等待翻页动画完成
+            yield return new WaitForSeconds(6f);
+            
+            // 显示所有数字的庆祝动画
+            Debug.Log("💰 ULTRA WIN CELEBRATION! 💰");
+            
+            // 更新所有相关数字
+            if (scoreRoll != null)
+                scoreRoll.AddValue(ultraWinAmount / 10); // 添加部分到分数
+            
+            if (balanceRoll != null)
+                balanceRoll.AddValue(ultraWinAmount); // 添加到余额
+        }
+        
+        private System.Collections.IEnumerator DelayedScoreUpdate(long amount, float delay)
+        {
+            yield return new WaitForSeconds(delay);
+            
+            if (scoreRoll != null)
+            {
+                scoreRoll.AddValue(amount);
+            }
+        }
+        
+        #endregion
+        
+        #region 游戏逻辑示例
+        
+        /// <summary>
+        /// 模拟老虎机获胜时的数字动画序列
+        /// </summary>
+        public void SimulateSlotWin(long winAmount)
+        {
+            // 1. 显示中奖金额
+            if (winAmountRoll != null)
+            {
+                winAmountRoll.SetValue(0);
+                winAmountRoll.RollToValue(winAmount, 2f);
+            }
+            
+            // 2. 延迟后更新分数和余额
+            StartCoroutine(UpdateScoreAndBalanceCoroutine(winAmount));
+        }
+        
+        private System.Collections.IEnumerator UpdateScoreAndBalanceCoroutine(long winAmount)
+        {
+            // 等待中奖金额动画完成
+            yield return new WaitForSeconds(2.5f);
+            
+            // 同时更新分数和余额
+            if (scoreRoll != null)
+                scoreRoll.AddValue(winAmount, 1.5f);
+            
+            if (balanceRoll != null)
+                balanceRoll.AddValue(winAmount, 1.5f);
+        }
+        
+        /// <summary>
+        /// 模拟奖池增长
+        /// </summary>
+        public void SimulateJackpotGrowth()
+        {
+            if (jackpotRoll != null)
+            {
+                // 随机增加奖池金额
+                long randomIncrease = Random.Range(1000, 10000);
+                jackpotRoll.AddValue(randomIncrease, 0.5f);
+            }
+        }
+        
+        /// <summary>
+        /// 模拟大奖级别检测和处理
+        /// </summary>
+        public void SimulateLargeWinDetection(long winAmount)
+        {
+            string winLevel = GetWinLevelDescription(winAmount);
+            Debug.Log($"Win detected: {winAmount:N0} - {winLevel}");
+            
+            // 根据奖金大小选择不同的显示组件
+            if (winAmount >= 1000000000000) // 1亿以上用翻页显示
+            {
+                if (ultraWinFlip != null)
+                {
+                    ultraWinFlip.SpinToValue(winAmount);
+                }
+            }
+            else if (winAmount >= 100000000000) // 1千万以上用翻页显示
+            {
+                if (megaJackpotFlip != null)
+                {
+                    megaJackpotFlip.SpinToValue(winAmount);
+                }
+            }
+            else // 普通奖金用滚动显示
+            {
+                if (winAmountRoll != null)
+                {
+                    winAmountRoll.RollToValue(winAmount);
+                }
+            }
+        }
+        
+        private string GetWinLevelDescription(long amount)
+        {
+            if (amount >= 1000000000000) return "ULTIMATE JACKPOT! 💎";
+            if (amount >= 100000000000) return "MEGA JACKPOT! 🏆";
+            if (amount >= 10000000000) return "SUPER JACKPOT! 🎊";
+            if (amount >= 1000000000) return "BIG JACKPOT! 🎉";
+            if (amount >= 100000000) return "Large Win! 💰";
+            if (amount >= 10000000) return "Good Win! 🎯";
+            return "Small Win";
+        }
+        
+        #endregion
+        
+        #region 事件回调
+        
+        private void OnWinRollComplete(long finalValue)
+        {
+            Debug.Log($"Win amount animation completed: {finalValue:N0}");
+            
+            // 可以在这里触发其他效果,比如粒子特效、音效等
+            // Trigger other effects like particles, sounds, etc.
+        }
+        
+        private void OnUltraWinComplete(long finalValue)
+        {
+            Debug.Log($"🌟 ULTRA WIN COMPLETED: {finalValue:N0} 🌟");
+            
+            // 超级大奖完成后的特殊处理
+            ShowUltraWinCelebration();
+        }
+        
+        private void ShowUltraWinCelebration()
+        {
+            // 这里可以触发最华丽的庆祝效果
+            Debug.Log("🎆🎆🎆 ULTIMATE CELEBRATION! 🎆🎆🎆");
+        }
+        
+        #endregion
+        
+        #region 公共接口
+        
+        /// <summary>
+        /// 设置分数
+        /// </summary>
+        public void SetScore(long score)
+        {
+            if (scoreRoll != null)
+                scoreRoll.SetValue(score);
+        }
+        
+        /// <summary>
+        /// 增加分数
+        /// </summary>
+        public void AddScore(long amount)
+        {
+            if (scoreRoll != null)
+                scoreRoll.AddValue(amount);
+        }
+        
+        /// <summary>
+        /// 设置余额
+        /// </summary>
+        public void SetBalance(long balance)
+        {
+            if (balanceRoll != null)
+                balanceRoll.SetValue(balance);
+        }
+        
+        /// <summary>
+        /// 更新余额
+        /// </summary>
+        public void UpdateBalance(long newBalance)
+        {
+            if (balanceRoll != null)
+                balanceRoll.RollToValue(newBalance);
+        }
+        
+        /// <summary>
+        /// 显示大奖动画
+        /// </summary>
+        public void ShowJackpotWin(long jackpotAmount)
+        {
+            if (winAmountRoll != null)
+            {
+                winAmountRoll.SetValue(0);
+                winAmountRoll.RollToValue(jackpotAmount, 5f); // 大奖用更长时间
+            }
+        }
+        
+        /// <summary>
+        /// 测试所有大数字效果
+        /// </summary>
+        public void TestAllLargeNumberEffects()
+        {
+            StartCoroutine(TestSequence());
+        }
+        
+        private System.Collections.IEnumerator TestSequence()
+        {
+            Debug.Log("开始大数字测试序列...");
+            
+            // 测试1: 大奖 (5千万)
+            OnLargeWin();
+            yield return new WaitForSeconds(6f);
+            
+            // 测试2: 超级大奖 (5亿)
+            OnMegaJackpot();
+            yield return new WaitForSeconds(8f);
+            
+            // 测试3: 终极大奖 (接近万亿)
+            OnUltraWin();
+            yield return new WaitForSeconds(10f);
+            
+            Debug.Log("大数字测试序列完成!");
+        }
+        
+        #endregion
+        
+        #region 调试方法
+        
+        [ContextMenu("Test Slot Win")]
+        private void TestSlotWin()
+        {
+            SimulateSlotWin(15000);
+        }
+        
+        [ContextMenu("Test Jackpot Growth")]
+        private void TestJackpotGrowth()
+        {
+            SimulateJackpotGrowth();
+        }
+        
+        [ContextMenu("Test Big Win")]
+        private void TestBigWin()
+        {
+            ShowJackpotWin(500000);
+        }
+        
+        [ContextMenu("Test Large Win Detection")]
+        private void TestLargeWinDetection()
+        {
+            SimulateLargeWinDetection(50000000); // 5千万
+        }
+        
+        [ContextMenu("Test All Large Number Effects")]
+        private void TestAllEffects()
+        {
+            TestAllLargeNumberEffects();
+        }
+        
+        [ContextMenu("Demo Ultra Jackpot")]
+        private void DemoUltraJackpot()
+        {
+            SimulateLargeWinDetection(999999999999); // 接近万亿
+        }
+        
+        #endregion
+    }
+} 
+```

+ 434 - 0
笔记文件/2.笔记/unity数字text滚动代码实现 代码缓存_第三章.md

@@ -0,0 +1,434 @@
+## SlotNumberManager
+管理器
+
+``` cs
+using System.Collections;
+using UnityEngine;
+
+namespace SlotGame
+{
+    /// <summary>
+    /// 老虎机数字管理器 - 统一管理所有数字滚动动画
+    /// Slot machine number manager - centrally manages all number rolling animations
+    /// </summary>
+    public class SlotNumberManager : MonoBehaviour
+    {
+        [Header("数字滚动组件 Number Roll Components")]
+        [SerializeField] private NumberRollAnimation scoreDisplay;
+        [SerializeField] private NumberRollAnimation balanceDisplay;
+        [SerializeField] private NumberRollAnimation jackpotDisplay;
+        [SerializeField] private NumberRollAnimation winAmountDisplay;
+        [SerializeField] private NumberRollAnimation betAmountDisplay;
+        
+        [Header("动画时间设置 Animation Timing")]
+        [SerializeField] private float scoreRollDuration = 1.5f;
+        [SerializeField] private float balanceRollDuration = 1.0f;
+        [SerializeField] private float jackpotRollDuration = 0.8f;
+        [SerializeField] private float winAmountRollDuration = 2.0f;
+        [SerializeField] private float bigWinRollDuration = 4.0f;
+        
+        [Header("数值设置 Value Settings")]
+        [SerializeField] private long currentScore = 0;
+        [SerializeField] private long currentBalance = 50000;
+        [SerializeField] private long currentJackpot = 3000000;
+        [SerializeField] private long currentBetAmount = 100;
+        
+        [Header("大奖阈值 Big Win Threshold")]
+        [SerializeField] private long bigWinThreshold = 100000;
+        
+        // 事件
+        public event System.Action<long> OnScoreChanged;
+        public event System.Action<long> OnBalanceChanged;
+        public event System.Action<long> OnJackpotChanged;
+        public event System.Action<long> OnWinAmountShown;
+        public event System.Action<long> OnBigWinTriggered;
+        
+        #region Unity生命周期
+        
+        private void Start()
+        {
+            InitializeDisplays();
+            RegisterEvents();
+        }
+        
+        private void OnDestroy()
+        {
+            UnregisterEvents();
+        }
+        
+        #endregion
+        
+        #region 初始化
+        
+        private void InitializeDisplays()
+        {
+            // 设置初始显示值
+            if (scoreDisplay != null)
+                scoreDisplay.SetValue(currentScore);
+            
+            if (balanceDisplay != null)
+                balanceDisplay.SetValue(currentBalance);
+            
+            if (jackpotDisplay != null)
+                jackpotDisplay.SetValue(currentJackpot);
+            
+            if (winAmountDisplay != null)
+                winAmountDisplay.SetValue(0);
+            
+            if (betAmountDisplay != null)
+                betAmountDisplay.SetValue(currentBetAmount);
+        }
+        
+        private void RegisterEvents()
+        {
+            if (scoreDisplay != null)
+                scoreDisplay.OnRollComplete += OnScoreRollComplete;
+            
+            if (balanceDisplay != null)
+                balanceDisplay.OnRollComplete += OnBalanceRollComplete;
+            
+            if (jackpotDisplay != null)
+                jackpotDisplay.OnRollComplete += OnJackpotRollComplete;
+            
+            if (winAmountDisplay != null)
+                winAmountDisplay.OnRollComplete += OnWinAmountRollComplete;
+        }
+        
+        private void UnregisterEvents()
+        {
+            if (scoreDisplay != null)
+                scoreDisplay.OnRollComplete -= OnScoreRollComplete;
+            
+            if (balanceDisplay != null)
+                balanceDisplay.OnRollComplete -= OnBalanceRollComplete;
+            
+            if (jackpotDisplay != null)
+                jackpotDisplay.OnRollComplete -= OnJackpotRollComplete;
+            
+            if (winAmountDisplay != null)
+                winAmountDisplay.OnRollComplete -= OnWinAmountRollComplete;
+        }
+        
+        #endregion
+        
+        #region 分数管理
+        
+        /// <summary>
+        /// 增加分数
+        /// </summary>
+        public void AddScore(long amount)
+        {
+            currentScore += amount;
+            if (scoreDisplay != null)
+            {
+                scoreDisplay.RollToValue(currentScore, scoreRollDuration);
+            }
+            OnScoreChanged?.Invoke(currentScore);
+        }
+        
+        /// <summary>
+        /// 设置分数
+        /// </summary>
+        public void SetScore(long score)
+        {
+            currentScore = score;
+            if (scoreDisplay != null)
+            {
+                scoreDisplay.SetValue(currentScore);
+            }
+            OnScoreChanged?.Invoke(currentScore);
+        }
+        
+        #endregion
+        
+        #region 余额管理
+        
+        /// <summary>
+        /// 增加余额
+        /// </summary>
+        public void AddBalance(long amount)
+        {
+            currentBalance += amount;
+            if (balanceDisplay != null)
+            {
+                balanceDisplay.RollToValue(currentBalance, balanceRollDuration);
+            }
+            OnBalanceChanged?.Invoke(currentBalance);
+        }
+        
+        /// <summary>
+        /// 扣除余额(下注)
+        /// </summary>
+        public bool DeductBalance(long amount)
+        {
+            if (currentBalance >= amount)
+            {
+                currentBalance -= amount;
+                if (balanceDisplay != null)
+                {
+                    balanceDisplay.RollToValue(currentBalance, balanceRollDuration);
+                }
+                OnBalanceChanged?.Invoke(currentBalance);
+                return true;
+            }
+            return false;
+        }
+        
+        /// <summary>
+        /// 设置余额
+        /// </summary>
+        public void SetBalance(long balance)
+        {
+            currentBalance = balance;
+            if (balanceDisplay != null)
+            {
+                balanceDisplay.SetValue(currentBalance);
+            }
+            OnBalanceChanged?.Invoke(currentBalance);
+        }
+        
+        #endregion
+        
+        #region 奖池管理
+        
+        /// <summary>
+        /// 增加奖池
+        /// </summary>
+        public void AddJackpot(long amount)
+        {
+            currentJackpot += amount;
+            if (jackpotDisplay != null)
+            {
+                jackpotDisplay.RollToValue(currentJackpot, jackpotRollDuration);
+            }
+            OnJackpotChanged?.Invoke(currentJackpot);
+        }
+        
+        /// <summary>
+        /// 重置奖池(中大奖后)
+        /// </summary>
+        public void ResetJackpot(long newAmount = 1000000)
+        {
+            currentJackpot = newAmount;
+            if (jackpotDisplay != null)
+            {
+                jackpotDisplay.RollToValue(currentJackpot, jackpotRollDuration);
+            }
+            OnJackpotChanged?.Invoke(currentJackpot);
+        }
+        
+        #endregion
+        
+        #region 中奖显示
+        
+        /// <summary>
+        /// 显示中奖金额
+        /// </summary>
+        public void ShowWinAmount(long winAmount)
+        {
+            if (winAmountDisplay != null)
+            {
+                winAmountDisplay.SetValue(0);
+                
+                // 根据中奖金额决定动画时长
+                float duration = winAmount >= bigWinThreshold ? bigWinRollDuration : winAmountRollDuration;
+                winAmountDisplay.RollToValue(winAmount, duration);
+                
+                // 检查是否是大奖
+                if (winAmount >= bigWinThreshold)
+                {
+                    OnBigWinTriggered?.Invoke(winAmount);
+                }
+            }
+            
+            OnWinAmountShown?.Invoke(winAmount);
+        }
+        
+        /// <summary>
+        /// 隐藏中奖金额显示
+        /// </summary>
+        public void HideWinAmount()
+        {
+            if (winAmountDisplay != null)
+            {
+                winAmountDisplay.SetValue(0);
+            }
+        }
+        
+        #endregion
+        
+        #region 下注金额
+        
+        /// <summary>
+        /// 设置下注金额
+        /// </summary>
+        public void SetBetAmount(long betAmount)
+        {
+            currentBetAmount = betAmount;
+            if (betAmountDisplay != null)
+            {
+                betAmountDisplay.SetValue(currentBetAmount);
+            }
+        }
+        
+        /// <summary>
+        /// 更新下注金额(带动画)
+        /// </summary>
+        public void UpdateBetAmount(long betAmount)
+        {
+            currentBetAmount = betAmount;
+            if (betAmountDisplay != null)
+            {
+                betAmountDisplay.RollToValue(currentBetAmount, 0.5f);
+            }
+        }
+        
+        #endregion
+        
+        #region 游戏流程
+        
+        /// <summary>
+        /// 开始游戏(扣除下注金额)
+        /// </summary>
+        public bool StartGame()
+        {
+            return DeductBalance(currentBetAmount);
+        }
+        
+        /// <summary>
+        /// 处理游戏结果
+        /// </summary>
+        public void ProcessGameResult(long winAmount, bool addToScore = true)
+        {
+            if (winAmount > 0)
+            {
+                // 显示中奖金额
+                ShowWinAmount(winAmount);
+                
+                // 启动协程处理后续动画
+                StartCoroutine(ProcessWinSequence(winAmount, addToScore));
+            }
+        }
+        
+        private IEnumerator ProcessWinSequence(long winAmount, bool addToScore)
+        {
+            // 等待中奖金额动画
+            float waitTime = winAmount >= bigWinThreshold ? bigWinRollDuration : winAmountRollDuration;
+            yield return new WaitForSeconds(waitTime + 0.5f);
+            
+            // 同时更新余额和分数
+            if (addToScore)
+            {
+                AddScore(winAmount);
+            }
+            AddBalance(winAmount);
+            
+            // 延迟后隐藏中奖显示
+            yield return new WaitForSeconds(2f);
+            HideWinAmount();
+        }
+        
+        /// <summary>
+        /// 中大奖流程
+        /// </summary>
+        public void ProcessJackpotWin()
+        {
+            long jackpotWin = currentJackpot;
+            
+            // 显示大奖金额
+            ShowWinAmount(jackpotWin);
+            
+            // 重置奖池
+            ResetJackpot();
+            
+            // 处理大奖结果
+            StartCoroutine(ProcessJackpotSequence(jackpotWin));
+        }
+        
+        private IEnumerator ProcessJackpotSequence(long jackpotAmount)
+        {
+            // 等待大奖动画
+            yield return new WaitForSeconds(bigWinRollDuration + 1f);
+            
+            // 更新余额和分数
+            AddScore(jackpotAmount);
+            AddBalance(jackpotAmount);
+            
+            // 延迟后隐藏显示
+            yield return new WaitForSeconds(3f);
+            HideWinAmount();
+        }
+        
+        #endregion
+        
+        #region 事件回调
+        
+        private void OnScoreRollComplete(long value)
+        {
+            Debug.Log($"Score roll completed: {value}");
+        }
+        
+        private void OnBalanceRollComplete(long value)
+        {
+            Debug.Log($"Balance roll completed: {value}");
+        }
+        
+        private void OnJackpotRollComplete(long value)
+        {
+            Debug.Log($"Jackpot roll completed: {value}");
+        }
+        
+        private void OnWinAmountRollComplete(long value)
+        {
+            Debug.Log($"Win amount roll completed: {value}");
+        }
+        
+        #endregion
+        
+        #region 属性访问器
+        
+        public long CurrentScore => currentScore;
+        public long CurrentBalance => currentBalance;
+        public long CurrentJackpot => currentJackpot;
+        public long CurrentBetAmount => currentBetAmount;
+        
+        public bool CanAffordBet => currentBalance >= currentBetAmount;
+        
+        #endregion
+        
+        #region 调试方法
+        
+        [ContextMenu("Test Small Win")]
+        private void TestSmallWin()
+        {
+            ProcessGameResult(5000);
+        }
+        
+        [ContextMenu("Test Big Win")]
+        private void TestBigWin()
+        {
+            ProcessGameResult(150000);
+        }
+        
+        [ContextMenu("Test Jackpot Win")]
+        private void TestJackpotWin()
+        {
+            ProcessJackpotWin();
+        }
+        
+        [ContextMenu("Add Balance 10000")]
+        private void TestAddBalance()
+        {
+            AddBalance(10000);
+        }
+        
+        [ContextMenu("Increase Jackpot")]
+        private void TestIncreaseJackpot()
+        {
+            AddJackpot(50000);
+        }
+        
+        #endregion
+    }
+} 
+```

+ 531 - 0
笔记文件/2.笔记/unity数字text滚动代码实现 代码缓存_第二章.md

@@ -0,0 +1,531 @@
+## FlipNumberDisplay
+翻页实现(未验证)
+
+``` cs
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace SlotGame
+{
+    /// <summary>
+    /// 翻页数字显示器 - 模拟机械老虎机的数字滚轮效果
+    /// Flip number display - simulates mechanical slot machine number wheel effects
+    /// </summary>
+    [System.Serializable]
+    public class DigitWheel
+    {
+        [Header("UI组件 UI Components")]
+        public RectTransform wheelContainer;
+        public List<Text> digitTexts = new List<Text>();
+        
+        [Header("动画设置 Animation Settings")]
+        public float spinSpeed = 1000f;
+        public AnimationCurve spinCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
+        
+        [HideInInspector] public int currentDigit = 0;
+        [HideInInspector] public bool isSpinning = false;
+        [HideInInspector] public Coroutine spinCoroutine;
+    }
+    
+    public class FlipNumberDisplay : MonoBehaviour
+    {
+        [Header("数字轮设置 Digit Wheel Setup")]
+        [SerializeField] private List<DigitWheel> digitWheels = new List<DigitWheel>();
+        [SerializeField] private int maxDigits = 12; // 增加到12位,支持千亿级别
+        [SerializeField] private float digitHeight = 60f;
+        
+        [Header("滚动设置 Spinning Settings")]
+        [SerializeField] private float baseDuration = 2f;
+        [SerializeField] private float extraDurationPerDigit = 0.3f;
+        [SerializeField] private bool spinFromRightToLeft = true;
+        [SerializeField] private float digitDelay = 0.1f;
+        
+        [Header("大数字优化 Large Number Optimization")]
+        [SerializeField] private bool enableLargeNumberMode = true;
+        [SerializeField] private long largeNumberThreshold = 10000000; // 1千万以上算大数字
+        [SerializeField] private float largeNumberSpeedMultiplier = 1.3f; // 大数字滚动速度倍数
+        [SerializeField] private int largeNumberMinSpins = 5; // 大数字最少转圈数
+        [SerializeField] private int largeNumberMaxSpins = 12; // 大数字最多转圈数
+        [SerializeField] private float largeNumberDelayReduction = 0.7f; // 大数字延迟减少倍数
+        [SerializeField] private bool enableSpectacularEffect = true; // 大数字华丽效果
+        
+        [Header("音效设置 Sound Settings")]
+        [SerializeField] private AudioClip spinSound;
+        [SerializeField] private AudioClip stopSound;
+        [SerializeField] private AudioClip largeNumberSound; // 大数字专用音效
+        [SerializeField] private AudioSource audioSource;
+        
+        [Header("调试 Debug")]
+        [SerializeField] private bool debugMode = false;
+        
+        private long currentValue = 0;
+        private long targetValue = 0;
+        private bool isAnimating = false;
+        
+        // 事件
+        public event System.Action<long> OnValueChanged;
+        public event System.Action<long> OnSpinComplete;
+        public event System.Action OnSpinStart;
+        public event System.Action<long> OnLargeNumberDetected; // 大数字检测事件
+        
+        #region Unity生命周期
+        
+        private void Awake()
+        {
+            InitializeWheels();
+        }
+        
+        private void Start()
+        {
+            if (audioSource == null)
+                audioSource = GetComponent<AudioSource>();
+        }
+        
+        #endregion
+        
+        #region 初始化
+        
+        private void InitializeWheels()
+        {
+            // 确保有足够的数字轮
+            while (digitWheels.Count < maxDigits)
+            {
+                digitWheels.Add(new DigitWheel());
+            }
+            
+            foreach (var wheel in digitWheels)
+            {
+                if (wheel.wheelContainer != null && wheel.digitTexts.Count == 0)
+                {
+                    CreateDigitTexts(wheel);
+                }
+                SetupWheelPositions(wheel);
+            }
+        }
+        
+        private void CreateDigitTexts(DigitWheel wheel)
+        {
+            // 为每个数字(0-9)创建文本组件,加上重复的首尾数字用于循环效果
+            for (int i = 0; i < 12; i++) // 0,1,2,3,4,5,6,7,8,9,0,1
+            {
+                GameObject digitObj = new GameObject($"Digit_{i % 10}");
+                digitObj.transform.SetParent(wheel.wheelContainer);
+                
+                Text digitText = digitObj.AddComponent<Text>();
+                digitText.text = (i % 10).ToString();
+                digitText.fontSize = 36;
+                digitText.alignment = TextAnchor.MiddleCenter;
+                digitText.color = Color.white;
+                
+                // 设置默认字体
+                digitText.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
+                
+                RectTransform rectTransform = digitText.rectTransform;
+                rectTransform.sizeDelta = new Vector2(digitHeight, digitHeight);
+                rectTransform.localScale = Vector3.one;
+                
+                wheel.digitTexts.Add(digitText);
+            }
+        }
+        
+        private void SetupWheelPositions(DigitWheel wheel)
+        {
+            if (wheel.digitTexts.Count == 0) return;
+            
+            for (int i = 0; i < wheel.digitTexts.Count; i++)
+            {
+                RectTransform rectTransform = wheel.digitTexts[i].rectTransform;
+                rectTransform.localPosition = new Vector3(0, (i - 1) * digitHeight, 0);
+            }
+        }
+        
+        #endregion
+        
+        #region 大数字检测和优化
+        
+        /// <summary>
+        /// 检查是否为大数字
+        /// </summary>
+        private bool IsLargeNumber(long value)
+        {
+            return enableLargeNumberMode && value >= largeNumberThreshold;
+        }
+        
+        /// <summary>
+        /// 获取大数字等级 (1=大数字, 2=超大数字, 3=极大数字)
+        /// </summary>
+        private int GetLargeNumberLevel(long value)
+        {
+            if (value >= 1000000000000) return 3; // 万亿级
+            if (value >= 10000000000) return 2;   // 百亿级
+            if (value >= largeNumberThreshold) return 1; // 千万级
+            return 0;
+        }
+        
+        /// <summary>
+        /// 根据数字大小计算优化参数
+        /// </summary>
+        private (float duration, float delay, int minSpins, int maxSpins) CalculateLargeNumberParams(long value)
+        {
+            int level = GetLargeNumberLevel(value);
+            
+            float duration = baseDuration;
+            float delay = digitDelay;
+            int minSpins = 3;
+            int maxSpins = 8;
+            
+            switch (level)
+            {
+                case 1: // 大数字
+                    duration *= largeNumberSpeedMultiplier;
+                    delay *= largeNumberDelayReduction;
+                    minSpins = largeNumberMinSpins;
+                    maxSpins = largeNumberMaxSpins;
+                    break;
+                case 2: // 超大数字
+                    duration *= largeNumberSpeedMultiplier * 1.2f;
+                    delay *= largeNumberDelayReduction * 0.8f;
+                    minSpins = largeNumberMinSpins + 2;
+                    maxSpins = largeNumberMaxSpins + 3;
+                    break;
+                case 3: // 极大数字
+                    duration *= largeNumberSpeedMultiplier * 1.5f;
+                    delay *= largeNumberDelayReduction * 0.6f;
+                    minSpins = largeNumberMinSpins + 4;
+                    maxSpins = largeNumberMaxSpins + 5;
+                    break;
+            }
+            
+            return (duration, delay, minSpins, maxSpins);
+        }
+        
+        #endregion
+        
+        #region 公共方法
+        
+        /// <summary>
+        /// 设置数值(无动画)
+        /// </summary>
+        public void SetValue(long value)
+        {
+            currentValue = value;
+            targetValue = value;
+            UpdateDisplayImmediate(value);
+            OnValueChanged?.Invoke(value);
+            
+            if (debugMode) Debug.Log($"FlipNumber: Set value to {value:N0}");
+        }
+        
+        /// <summary>
+        /// 滚动到目标值
+        /// </summary>
+        public void SpinToValue(long targetValue, float? customDuration = null)
+        {
+            if (isAnimating)
+            {
+                StopAllSpins();
+            }
+            
+            this.targetValue = targetValue;
+            
+            // 检测大数字并触发事件
+            if (IsLargeNumber(targetValue))
+            {
+                OnLargeNumberDetected?.Invoke(targetValue);
+                if (debugMode) Debug.Log($"FlipNumber: Large number detected: {targetValue:N0} (Level {GetLargeNumberLevel(targetValue)})");
+            }
+            
+            StartCoroutine(SpinSequence(currentValue, targetValue, customDuration));
+            
+            if (debugMode) Debug.Log($"FlipNumber: Spinning from {currentValue:N0} to {targetValue:N0}");
+        }
+        
+        /// <summary>
+        /// 增加数值
+        /// </summary>
+        public void AddValue(long addAmount, float? customDuration = null)
+        {
+            long newTarget = currentValue + addAmount;
+            SpinToValue(newTarget, customDuration);
+        }
+        
+        /// <summary>
+        /// 停止所有滚动
+        /// </summary>
+        public void StopAllSpins()
+        {
+            if (!isAnimating) return;
+            
+            StopAllCoroutines();
+            isAnimating = false;
+            
+            foreach (var wheel in digitWheels)
+            {
+                if (wheel.spinCoroutine != null)
+                {
+                    StopCoroutine(wheel.spinCoroutine);
+                    wheel.spinCoroutine = null;
+                }
+                wheel.isSpinning = false;
+            }
+            
+            UpdateDisplayImmediate(targetValue);
+            currentValue = targetValue;
+        }
+        
+        #endregion
+        
+        #region 滚动动画
+        
+        private IEnumerator SpinSequence(long startValue, long endValue, float? customDuration)
+        {
+            isAnimating = true;
+            OnSpinStart?.Invoke();
+            
+            // 根据数字大小选择音效
+            AudioClip soundToPlay = IsLargeNumber(endValue) && largeNumberSound != null ? largeNumberSound : spinSound;
+            
+            // 播放滚动音效
+            if (soundToPlay != null && audioSource != null)
+            {
+                audioSource.clip = soundToPlay;
+                audioSource.loop = true;
+                audioSource.Play();
+            }
+            
+            string startStr = startValue.ToString().PadLeft(maxDigits, '0');
+            string endStr = endValue.ToString().PadLeft(maxDigits, '0');
+            
+            // 获取大数字优化参数
+            var (optimizedDuration, optimizedDelay, minSpins, maxSpins) = CalculateLargeNumberParams(endValue);
+            
+            // 计算动画时长
+            float totalDuration = customDuration ?? (optimizedDuration + (endStr.Length * extraDurationPerDigit));
+            
+            if (debugMode && IsLargeNumber(endValue))
+            {
+                Debug.Log($"FlipNumber: Using large number optimization - Duration: {totalDuration:F2}s, Delay: {optimizedDelay:F2}s, Spins: {minSpins}-{maxSpins}");
+            }
+            
+            // 按顺序启动每个数字轮的滚动
+            List<Coroutine> spinCoroutines = new List<Coroutine>();
+            
+            for (int i = 0; i < digitWheels.Count && i < endStr.Length; i++)
+            {
+                int digitIndex = spinFromRightToLeft ? (endStr.Length - 1 - i) : i;
+                
+                if (digitIndex < digitWheels.Count)
+                {
+                    int startDigit = digitIndex < startStr.Length ? int.Parse(startStr[digitIndex].ToString()) : 0;
+                    int endDigit = int.Parse(endStr[digitIndex].ToString());
+                    
+                    yield return new WaitForSeconds(optimizedDelay);
+                    
+                    Coroutine spinCoroutine = StartCoroutine(SpinDigitWheel(
+                        digitWheels[digitIndex], 
+                        startDigit, 
+                        endDigit, 
+                        totalDuration - (i * optimizedDelay),
+                        minSpins,
+                        maxSpins
+                    ));
+                    
+                    spinCoroutines.Add(spinCoroutine);
+                }
+            }
+            
+            // 等待所有滚动完成
+            while (spinCoroutines.Count > 0)
+            {
+                for (int i = spinCoroutines.Count - 1; i >= 0; i--)
+                {
+                    if (spinCoroutines[i] == null)
+                    {
+                        spinCoroutines.RemoveAt(i);
+                    }
+                }
+                yield return null;
+            }
+            
+            // 停止音效,播放停止音效
+            if (audioSource != null)
+            {
+                audioSource.Stop();
+                if (stopSound != null)
+                {
+                    audioSource.PlayOneShot(stopSound);
+                }
+            }
+            
+            currentValue = endValue;
+            isAnimating = false;
+            
+            OnValueChanged?.Invoke(currentValue);
+            OnSpinComplete?.Invoke(currentValue);
+            
+            if (debugMode) Debug.Log($"FlipNumber: Spin completed at {currentValue:N0}");
+        }
+        
+        private IEnumerator SpinDigitWheel(DigitWheel wheel, int startDigit, int endDigit, float duration, int minSpins, int maxSpins)
+        {
+            if (wheel.wheelContainer == null || wheel.digitTexts.Count == 0)
+                yield break;
+            
+            wheel.isSpinning = true;
+            float elapsedTime = 0f;
+            
+            // 计算总的旋转圈数和最终位置
+            int totalSpins = Random.Range(minSpins, maxSpins + 1);
+            float totalRotation = (totalSpins * 10 + (endDigit - startDigit + 10) % 10) * digitHeight;
+            
+            float startY = -startDigit * digitHeight;
+            float endY = startY - totalRotation;
+            
+            while (elapsedTime < duration)
+            {
+                elapsedTime += Time.deltaTime;
+                float progress = elapsedTime / duration;
+                float curveProgress = wheel.spinCurve.Evaluate(progress);
+                
+                float currentY = Mathf.Lerp(startY, endY, curveProgress);
+                wheel.wheelContainer.localPosition = new Vector3(0, currentY, 0);
+                
+                // 大数字华丽效果:动态缩放
+                if (enableSpectacularEffect && IsLargeNumber(targetValue))
+                {
+                    float scaleEffect = 1f + Mathf.Sin(progress * Mathf.PI * 6) * 0.05f; // 轻微的缩放动画
+                    wheel.wheelContainer.localScale = Vector3.one * scaleEffect;
+                }
+                
+                yield return null;
+            }
+            
+            // 确保最终位置和缩放正确
+            wheel.wheelContainer.localPosition = new Vector3(0, -endDigit * digitHeight, 0);
+            wheel.wheelContainer.localScale = Vector3.one;
+            wheel.currentDigit = endDigit;
+            wheel.isSpinning = false;
+            wheel.spinCoroutine = null;
+        }
+        
+        #endregion
+        
+        #region 显示更新
+        
+        private void UpdateDisplayImmediate(long value)
+        {
+            string valueStr = value.ToString().PadLeft(maxDigits, '0');
+            
+            for (int i = 0; i < digitWheels.Count && i < valueStr.Length; i++)
+            {
+                int digit = int.Parse(valueStr[i].ToString());
+                var wheel = digitWheels[i];
+                
+                if (wheel.wheelContainer != null)
+                {
+                    wheel.wheelContainer.localPosition = new Vector3(0, -digit * digitHeight, 0);
+                    wheel.wheelContainer.localScale = Vector3.one;
+                    wheel.currentDigit = digit;
+                }
+            }
+        }
+        
+        #endregion
+        
+        #region 属性访问器
+        
+        public long CurrentValue => currentValue;
+        public long TargetValue => targetValue;
+        public bool IsAnimating => isAnimating;
+        public bool IsCurrentValueLarge => IsLargeNumber(currentValue);
+        public int CurrentLargeNumberLevel => GetLargeNumberLevel(currentValue);
+        
+        #endregion
+        
+        #region 工具方法
+        
+        /// <summary>
+        /// 设置数字轮的颜色
+        /// </summary>
+        public void SetDigitColor(Color color)
+        {
+            foreach (var wheel in digitWheels)
+            {
+                foreach (var digitText in wheel.digitTexts)
+                {
+                    if (digitText != null)
+                        digitText.color = color;
+                }
+            }
+        }
+        
+        /// <summary>
+        /// 设置数字轮的字体大小
+        /// </summary>
+        public void SetFontSize(int fontSize)
+        {
+            foreach (var wheel in digitWheels)
+            {
+                foreach (var digitText in wheel.digitTexts)
+                {
+                    if (digitText != null)
+                        digitText.fontSize = fontSize;
+                }
+            }
+        }
+        
+        /// <summary>
+        /// 为大数字设置特殊颜色效果
+        /// </summary>
+        public void SetLargeNumberColorEffect(Color normalColor, Color largeNumberColor)
+        {
+            Color colorToUse = IsLargeNumber(currentValue) ? largeNumberColor : normalColor;
+            SetDigitColor(colorToUse);
+        }
+        
+        #endregion
+        
+        #region 调试方法
+        
+        [ContextMenu("Test Spin +1000")]
+        private void TestSpin1000()
+        {
+            AddValue(1000);
+        }
+        
+        [ContextMenu("Test Spin +10000")]
+        private void TestSpin10000()
+        {
+            AddValue(10000);
+        }
+        
+        [ContextMenu("Test Large Number 50000000")]
+        private void TestLargeNumber()
+        {
+            SpinToValue(50000000); // 5千万
+        }
+        
+        [ContextMenu("Test Ultra Large Number 5000000000")]
+        private void TestUltraLargeNumber()
+        {
+            SpinToValue(5000000000); // 50亿
+        }
+        
+        [ContextMenu("Test Mega Jackpot 999999999999")]
+        private void TestMegaJackpot()
+        {
+            SpinToValue(999999999999); // 接近万亿
+        }
+        
+        [ContextMenu("Test Reset to 0")]
+        private void TestReset()
+        {
+            SetValue(0);
+        }
+        
+        #endregion
+    }
+} 
+```

+ 3 - 2
笔记文件/日记/2025_07_10_星期四.md

@@ -21,8 +21,8 @@
 
 # 今日任务
 
-- [ ] 把所有序列帧动效都加上
-- [ ] 艺术数字滚动增加
+- [x] 序列帧动效逻辑处理
+- [x] 艺术数字滚动增加逻辑处理
 - [ ] 把音效也沟通加上
 - [ ] 完善剩余的实现逻辑
 - [ ] 调平滑的动画效果
@@ -31,4 +31,5 @@
 - [ ] 灵动平台 在Plink中台库,和AMP埋点整合一下
 ---
 [[unity动画序列帧代码实现 代码缓存]]
+[[unity数字text滚动代码实现 代码缓存]]
 # Journal