| //-------------------------------------------------------- | 
| //    [Author]:           第二世界 | 
| //    [  Date ]:           Monday, September 11, 2017 | 
| //-------------------------------------------------------- | 
| using UnityEngine; | 
| using System.Collections; | 
| using UnityEngine.UI; | 
|   | 
| using System.Text; | 
|   | 
| public class BossLifeBar : MonoBehaviour | 
| { | 
|     [SerializeField] Sprite[] m_LifeBarSprites; | 
|   | 
|     [SerializeField] Image m_BackGround; | 
|     [SerializeField] Image m_MiddleGround; | 
|     [SerializeField] Image m_PrefaceGround; | 
|   | 
|     [SerializeField] Slider m_SliderMiddleground; | 
|     [SerializeField] Slider m_SliderForeground; | 
|   | 
|     [SerializeField] Text m_Surplus; | 
|   | 
|     [SerializeField] Text m_SurplusPercent; | 
|      | 
|   | 
|     [SerializeField] float m_SmoothTime = 0.3f; | 
|     public float smoothTime { | 
|         get { return m_SmoothTime; } | 
|     } | 
|   | 
|     Pattern pattern = Pattern.Reduce; | 
|     float targetValue = 0f; | 
|     int totalSegments = 1; | 
|     int surplusSegments = -1; | 
|   | 
|     float refValue = 0f; | 
|     float timer = 0f; | 
|     float behaviourStartValue = 0f; | 
|   | 
|     float m_CurrentBehaviourValue = 0f; | 
|     float currentBehaviourValue { | 
|         get { return m_CurrentBehaviourValue; } | 
|         set { | 
|             m_CurrentBehaviourValue = value; | 
|             UpdateSurplusSegments(currentBehaviourValue); | 
|   | 
|             float behaviourDecimalValue = GetSegmentDecimal(m_CurrentBehaviourValue); | 
|             float trueDecimalValue = GetSegmentDecimal(targetValue); | 
|   | 
|             switch (pattern) | 
|             { | 
|                 case Pattern.Add: | 
|                     m_SliderForeground.value = behaviourDecimalValue; | 
|                     m_SliderMiddleground.value = behaviourDecimalValue > trueDecimalValue ? 1f : trueDecimalValue; | 
|                     break; | 
|                 case Pattern.Reduce: | 
|                     m_SliderMiddleground.value = behaviourDecimalValue; | 
|                     m_SliderForeground.value = behaviourDecimalValue < trueDecimalValue ? 0f : trueDecimalValue; | 
|                     break; | 
|                 case Pattern.None: | 
|                     m_SliderMiddleground.value = behaviourDecimalValue; | 
|                     m_SliderForeground.value = behaviourDecimalValue; | 
|                     break; | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void SetBaseInfo(int _lifeBarCount, ulong _hp, ulong _maxHp) | 
|     { | 
|         surplusSegments = -1; | 
|         totalSegments = _lifeBarCount; | 
|   | 
|         // 使用精确值,不再人为减小 | 
|         float percentage = (_maxHp > 0) ? (float)_hp / (float)_maxHp : 0f; | 
|         targetValue = currentBehaviourValue = percentage * totalSegments; | 
|   | 
|         // 使用统一的 GetSegmentDecimal,避免小数精度导致进度条为0 | 
|         var behaviourDecimalValue = GetSegmentDecimal(currentBehaviourValue); | 
|         m_SliderForeground.value = m_SliderMiddleground.value = behaviourDecimalValue; | 
|   | 
|         refValue = 0f; | 
|   | 
|         // 立刻显示基准百分比(使用 percentage) | 
|         m_SurplusPercent.text = (percentage * 100f).ToString("F2") + "%"; | 
|     } | 
|   | 
|     public void Show(ulong _hp, ulong _maxHp) | 
|     { | 
|         var percentage = Mathf.Clamp(_hp, 0, _maxHp) / (float)_maxHp; | 
|         var tempValue = totalSegments * percentage; // 不再减小 | 
|         pattern = tempValue > targetValue ? Pattern.Add : tempValue < targetValue ? Pattern.Reduce : Pattern.None; | 
|   | 
|         behaviourStartValue = currentBehaviourValue; | 
|         targetValue = tempValue; | 
|   | 
|         timer = 0f; | 
|         refValue = 0f; | 
|   | 
|         // 立即更新百分比显示(直接使用 percentage) | 
|         m_SurplusPercent.text = (percentage * 100f).ToString("F2") + "%"; | 
|     } | 
|   | 
|     private void LateUpdate() | 
|     { | 
|         if (Mathf.Abs(currentBehaviourValue - targetValue) > 0.00001f) | 
|         { | 
|             var newValue = Mathf.SmoothDamp(currentBehaviourValue, targetValue, ref refValue, smoothTime); | 
|             currentBehaviourValue = newValue; | 
|         } | 
|     } | 
|   | 
|     static StringBuilder stringBuild = new StringBuilder(); | 
|     private void UpdateSurplusSegments(float _targetValue) | 
|     { | 
|         var currentSurplus = Mathf.CeilToInt(_targetValue); | 
|         if (currentSurplus != surplusSegments) | 
|         { | 
|             surplusSegments = currentSurplus; | 
|             var colorSetLength = m_LifeBarSprites.Length; | 
|             var index = surplusSegments % colorSetLength; | 
|             var nextIndex = index == 0 ? colorSetLength - 1 : index - 1; | 
|   | 
|             m_PrefaceGround.overrideSprite = m_LifeBarSprites[index]; | 
|             m_MiddleGround.overrideSprite = m_LifeBarSprites[index]; | 
|             m_BackGround.overrideSprite = m_LifeBarSprites[nextIndex]; | 
|   | 
|             m_BackGround.SetActive(surplusSegments > 1); | 
|   | 
|             m_Surplus.text = "x" + surplusSegments.ToString(); | 
|             float pct = totalSegments > 0 ? Mathf.Clamp01(_targetValue / totalSegments) : 0f; | 
|             // 修复格式并处理接近 100% 的情况 | 
|             if (1f - pct < 0.00005f) pct = 1f; | 
|             m_SurplusPercent.text = (pct * 100f).ToString("F2") + "%"; | 
|         } | 
|     } | 
|   | 
|     // int GetNumKey(int _num) | 
|     // { | 
|     //     var config = DamageNumConfig.Get("BossLifeBarSurplusNum"); | 
|     //     return config.nums[_num - 48]; | 
|     // } | 
|   | 
|   | 
|     enum Pattern | 
|     { | 
|         None, | 
|         Add, | 
|         Reduce, | 
|     } | 
|   | 
|     // helper: 返回段内小数部分;当恰好为整数且大于0时,返回1以表示满格(避免0导致进度条变空) | 
|     private float GetSegmentDecimal(float value) | 
|     { | 
|         if (value <= 0f) return 0f; | 
|   | 
|         // 使用一个小的容忍值来处理浮点误差,避免 near-integer 导致 0 | 
|         const float eps = 1e-5f; | 
|   | 
|         // 先做一个向下稳定的 floor,避免 2.999999 变成 2 的问题 | 
|         float stableFloor = Mathf.Floor(value + eps); | 
|         float frac = value - stableFloor; | 
|   | 
|         if (frac <= eps) | 
|             return 1f; // 视为整段,显示满格 | 
|         return Mathf.Clamp01(frac); | 
|     } | 
|   | 
| } |