using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; public class ExtendSlider : MonoBehaviour { [SerializeField] Slider slider; [SerializeField] Color[] colorLevelPerRate; [SerializeField] MaskableGraphic currentColorIndicator; [SerializeField] MaskableGraphic prevColorIndicator; [Range(0f, 10f)] [SerializeField] float animSpeed = 0f; float currentRate; float targetRate; int prevColorIdx = -1; bool HasColorLevel => colorLevelPerRate.Length > 0; public UnityEvent OnChangedColorLevel; private void Update() { if (!HasColorLevel) { if (animSpeed > 0f) { float diff = targetRate - currentRate; float delta = diff * animSpeed * Time.fixedDeltaTime; if (Mathf.Abs(delta) >= Mathf.Abs(diff)) currentRate = targetRate; else currentRate += delta; } else { currentRate = targetRate; } slider.value = currentRate; } else { if (animSpeed > 0f) { float diff = targetRate - currentRate; float delta = diff * animSpeed * Time.fixedDeltaTime; if (Mathf.Abs(delta) >= Mathf.Abs(diff)) currentRate = targetRate; else currentRate += delta; } else { currentRate = targetRate; } GetColorIdxAndInnerRate(currentRate, out int colorIdx, out float innerRate); slider.value = innerRate; if (prevColorIdx != colorIdx) { if (currentColorIndicator != null) currentColorIndicator.color = colorLevelPerRate[colorIdx]; if (prevColorIndicator != null) prevColorIndicator.color = colorIdx > 0 ? colorLevelPerRate[colorIdx - 1] : new Color(1f, 1f, 1f, 0.5f); OnChangedColorLevel?.Invoke(innerRate); prevColorIdx = colorIdx; } } } private void GetColorIdxAndInnerRate(float rate, out int colorIdx, out float innerRate) { colorIdx = Mathf.FloorToInt(rate); innerRate = rate - colorIdx; // 색의 경계선(마지막 레이트 값은 제외)에 있으면 이전 레벨로 색 표시. if (rate > 0 && innerRate == 0) { --colorIdx; innerRate = 1f; } } public void SetRate(float rate) { rate = Mathf.Clamp01(rate); if(HasColorLevel) { targetRate = rate * colorLevelPerRate.Length; } else { targetRate = rate; } } public void SetRate(float currentValue, float maxValue) { if (maxValue == 0) SetRate(0); else SetRate(currentValue / maxValue); } public void SetRateImmediate(float rate) { rate = Mathf.Clamp01(rate); if (HasColorLevel) { targetRate = rate * colorLevelPerRate.Length; currentRate = targetRate; GetColorIdxAndInnerRate(currentRate, out int colorIdx, out float innerRate); slider.value = innerRate; if (prevColorIdx != colorIdx) { if (currentColorIndicator != null) currentColorIndicator.color = colorLevelPerRate[colorIdx]; if (prevColorIndicator != null) prevColorIndicator.color = colorIdx > 0 ? colorLevelPerRate[colorIdx - 1] : new Color(1f, 1f, 1f, 0.5f); OnChangedColorLevel?.Invoke(innerRate); prevColorIdx = colorIdx; } } else { targetRate = rate; currentRate = rate; slider.value = rate; } } public void SetRateImmediate(float currentValue, float maxValue) { if (maxValue == 0) SetRateImmediate(0); else SetRateImmediate(currentValue / maxValue); } private void OnValidate() { if (slider == null) slider = GetComponent(); } }