How to change a value over specified time?

So I have recently been wondering about how I could change a value (basically Lerp it) over a specific, predictable, amount of time… The only way I have been able to successfully do this currently is by using itweens valueTo method… Not exactly ideal IMO. For one it requires itween and for another it also requires the use of a callback method. I looked through the unity documentation and Mathf.SmoothStep looks basically what I was looking for!!! Unfortunately I can’t seem to get it to work! As I read the documentation I feed it the from value, the to value, and a time measurement and it will interpolate the values. I’ve tried implementing this a few different ways now. I’m not on the machine with that code on it but I can mock up what I’ve tried really quickly!!!

I’ve tried to implement it like a Lerp, but that won’t work…

IEnumerator smoothSteppin () {
	float timer = 10f;
	while (timer >= 0) {
		value = Mathf.SmoothStep(from, to, timer);
		timer -= Timer.deltaTime;
		yield return null;
	}
}

I’ve tried to just wait for it to complete.

IEnumerator smoothSteppin () {
	float timer = 10f;
	value = Mathf.SmoothStep(from, to, timer);
	yield return new WaitForSeconds(timer);
}

However in all these cases it seems to just JUMP to it’s upper limit. How am I supposed to use this? More importantly how can I most cleanly accomplish my goal (moving a float to a specified value over a predictable time) using only built in unity functions? Thanks a lot for the help!

The third parameter needs to be a value between 0 and 1; 1 being the to value, 0 being the from value and 0.5 is the average of the two. So in order to get your scripts to work, the only thing you need to do is divide timer by the total amount of time you want it to take. If you want it to go from from to to, just change timer to increase instead of decrease.

    IEnumerator smoothSteppin () {
     float timer = 10f;
     float timeToTake = 10f;
     while (timer >= 0) {
      value = Mathf.SmoothStep(from, to, timer/timeToTake);
      timer -= Timer.deltaTime;
      yield return null;
     }
    }

You have two problems.

  1. Smooth Step is from [0,1]. Hence at 10 you are way beyond the range.
  2. It looks like you’re interpolating in the wrong direction. Starting at 10 and going to zero will move you from to to from if that makes any sense. :slight_smile:

I think you want something that looks more like this:

IEnumerator SmoothSteppin (float duration) {
    var timer = 0f;
    while (timer <= duration) {
    //Count the other direction.  Its simpler. Or you can do (10-timer) in your
    //SmoothStep Calculation
       value = Mathf.SmoothStep( from , to , timer/duration );
       //Divide by 10 to put the timer back in the range of SmoothStep.
       timer += Time.deltaTime;
       yield return null;
    }
}

EDIT

So you want to be able to start a timer, and then have a value interpolate? The hard part about this is that you can’t use ref or out when you’re using a yield. I think your best bet might be to make a helper Class that can store the values and do this for you.

public class LerpTimer {

     private float startTime;
     
     private float t;
     private float f;
     private float d;

     private bool started = false;

     public float ElapsedTime {
          get {
               if (started) 
                    return Time.time - startTime;
               else
                    return 0;
           }
      }

      public float Value {
            get {
                 if (started) 
                     return Mathf.SmoothStep( f , t , (ElapsedTime) / d );
                 else 
                     return f;
            }
      }

     public LerpTimer (float from , float to , float duration ) {
          t = to;
          f = from;
          d = duration;
     }

     public void Start () {
          startTime = Time.time;
          started = true;
     }
}

This is pretty basic, but it sounds like it does everything that you want. You’d use it something like this:

var timer = new LerpTimer ( 0 , 10 , 10)
timer.Start();

//Wait a while......

someVariable = timer.Value;