How do I smooth my slider value in unity?

Viewed 1673

I have a script which updates the slider value based on slowMotionTimeLeft, to decreaseslowMotionTimeLeft. I am using a for loop with a coroutine which has a delay of 1 second, like this:

IEnumerator DecreaseSlowMotionTime()
{
    for(int i = 0; i < 5f; i++)
    {
        slowMotionTimeLeft -= 1f; // decrease slow motion

        ///<summary>
        /// if slow motion time is less than or equal to 0 break the loop
        /// </summary>
        if (slowMotionTimeLeft <= 0f)
        {
            onSlowMotion = false; 
            break;
        }
        yield return new WaitForSecondsRealtime(1f); // delay
    }   
}

now I have a slider, I want to smoothly update that value based on slowMotiontimeLeft, but it is not smooth, it is updating every second like the coroutine, I tried to lerp the values but it does not work. Here is the script:

// Slow Motion Bar
[Header("Slow Motion Slider Bar")]
[SerializeField] private Slider slowMoLeft;
[SerializeField] private float slowSliderSmoothSpeed = 0.125f;

// Other
private Player playerScript;

void Awake()
{
    playerScript = FindObjectOfType<Player>();
}

void Update()
{
    UpdateSlowMoSlider();
}

public void UpdateSlowMoSlider()
{
    slowMoLeft.value = playerScript.slowMotionTimeLeft;
}

any tips of what can I do? do I need to update the coroutine timer to make wait 0.1 seconds?

2 Answers

I'd do it in Update:

// Remove the IEnumerator DecreaseSlowMotionTime(), instead add this, or if you already use Update() add the content of this method to Update()
public void Update()
{
    if (slowMotionTimeLeft > 0)
    {
        slowMotionTimeLeft -= 1f * Time.deltaTime;
    }
}
// Slow Motion Bar
[Header("Slow Motion Slider Bar")]
[SerializeField] private Slider slowMoLeft;
[SerializeField] private float slowSliderSmoothSpeed = 0.125f;

// Other
private Player playerScript;

void Awake()
{
    playerScript = FindObjectOfType<Player>();
}

void Update()
{
    
    slowMoLeft.value = playerScript.slowMotionTimeLeft;
}

You can make your code better:

Instead of updating your slowMotionTimeLeft once every second, you can do something like this:

IEnumerator DecreaseSlowMotionTime()
{
    while (onSlowMotion)
    {
        // decrease slow motion without considering Time.timeScale
        slowMotionTimeLeft -= Time.unscaledDeltaTime; 

        // if slow motion time is less than or equal to 0 break the loop
        if (slowMotionTimeLeft <= 0f)
        {
            onSlowMotion = false; 
        }

        // will execute again in the next frame
        yield return null; 
    }   
}

Then your slider will reduce smoothly and at a 1:1 time speed.

Related