Mathf.Lerp help required

Hi,

I have the following snippet of code :

    void changePathCurvature()
    {
        // x - Get current value of CurvatureX
        currentCurvatureX = x;

        // newCurvatureX = Random within a range of -50 and 50
        newCurvatureX = (Random.Range(-50.0f, 50.0f));

        // x = Lerp currentCurvatureX to newCurvatureX over timeInterval
        x = Mathf.Lerp(currentCurvatureX, newCurvatureX, timeInterval);

        // y - Get current value of CurvatureY
        currentCurvatureY = y;

        // newCurvatureY = Random within a range of -50 and 50
        newCurvatureY = (Random.Range(-50.0f, 50.0f));

        // y = Lerp currentCurvatureY to newCurvatureY over timeInterval
        y = Mathf.Lerp(currentCurvatureY, newCurvatureY, timeInterval);
    }

it works, but the lerp does not do what is is supposed to do, I want it to smooth from a to b over a timeInterval I have set, it currently just jumps into position, I’m aware of it, and have tried variations within the code use time.time and time.deltaTime and nothing is really working out for me, any help would be greatly appreciated.

Lerp doesn’t work like that. The 3rd parameter is really a percentage with 0 being 0 and 1 being 100.

So you run the lerp command each frame and slowly increment the 3rd parameter from 0 to 1, usually using Time.deltaTime.

1 Like

This is a cool article about the subject : link

1 Like

Hi, so I’ve been pulling my hair out over this, I’ve been unable to find any viable solution to my problem.

My code is accessed from InvokeRepeating

void Start ()
{
    // Other stuff here....

    InvokeRepeating("changePathCurvature", timeInterval, timeInterval);
}

and my code as posted before :

void changePathCurvature()
    {
        // x - Get current value of CurvatureX
        currentCurvatureX = x;

        // newCurvatureX = Random within a range of -50 and 50
        newCurvatureX = (Random.Range(-50.0f, 50.0f));

        // x = Lerp currentCurvatureX to newCurvatureX over timeInterval
        x = Mathf.Lerp(currentCurvatureX, newCurvatureX, timeInterval);

        // y - Get current value of CurvatureY
        currentCurvatureY = y;

        // newCurvatureY = Random within a range of -50 and 50
        newCurvatureY = (Random.Range(-50.0f, 50.0f));

        // y = Lerp currentCurvatureY to newCurvatureY over timeInterval
        y = Mathf.Lerp(currentCurvatureY, newCurvatureY, timeInterval);
    }

so far, I’ve tried using Time.deltatime, getting my currentLerpTime and dividing it by timeInterval to get a value which is then clamped between 0 and 1, I then use this Percentage value as the ‘time’ part of my lerp, still jumps.

A lot of the tutorials / codes snippets / blog posts I’ve read seem to deal with movement of objects, whereas I just want to lerp from 1 value to another value over a given set of time ( timeInterval ), and I just can’t seem to figure it out, it either jumps directly to the end value or is clamped completely to values between 0 and 1, which means it ‘never’ reaches the final end point.

To be specific, it’s a curved horizon shader I’m controlling, I simply want to alter the curvature over time, to put it bluntly, let’s sat my timeInterval is 30, I invoke ( Repeating forever ) this function, so randomly change every 30 seconds and the start and end positions should also take 30 seconds to smoothly lerp into place, before changing again, the random range should give me the effect of rolling curves / inclines / declines and left and right bends.

Would ‘really’ appreciated any further help ? :frowning:

I would suggest a tweening engine where you can specify two values and a time interval so that it can handle all the other stuff for you. Both dotween and leantween have a free version that works great. Otherwise, you will have to figure out how far you need to move (what percent) to get to where you want to go. Usually this is done by taking the value 0(your starting point) creating a loop where you add an amount to 0 and using that to set the third parameter, thus gradually incrementing it over an amount of time. You’ll usually see while loops with a time.deltatime multiplied by a speed variable to get this effect and smooth things out.

Honestly, I currently don’t use Lerp in my work projects since we use a tweening engine to handle things.

1 Like

You could change the entire thing into a Coroutine:

IEnumerator MyLerp(){
   // This should work just like InvokeRepeating
   while(true) {
      float startval = startingval;
      float endval = endingval;
      float runtime = 30;
      float t = 0;
      for(t = 0; t <= runtime; t+=time.deltaTime) {
         whateverVar = Mathf.Lerp(startval, endval, t / runtime);
         yield return null;
       }
      // maybe set to end value here if it's not exact?
   }
}

Pretty sure that would do what you’re looking for. I used somewhat silly variable names, but I think the essence is there for you. Lerp needs the starting and ending values, and returns whatever fractional / linear evaluation between them.

1 Like

Hello, @methos5k

Actually, not to discount any of the other help I’ve received, but so far that code snippet has already been a massive help, I’ve been able to create a quick test, and it’s working splendidly. Just need to implement this into my main codebase now, I can’t thank you enough ! :slight_smile: :sweat_smile:

Sylon posted a great article about how Lerp works and how its often misused.

This is the formula for Lerp:

public float Lerp( float a, float b, float percent)
{
    percent = Mathf.Clamp(percent, 0, 1); // clamps percent to always be between 0~1

    return b*percent + a*(1-percent);

}

Thats basically it. its not something super fancy.

you just need to specify a Start value (NOT a current value!) and an end value. and then increase the percent value as needed
I typically write Animated Lerps in Coroutines

    private void Start()
    {
        StartCoroutine(ChangeCurvePath(30.0));//change the curve every 30 seconds
    }

    private IEnumerator ChangeCurvePath(float frequency)
    {
        Coroutine xHandle = null;
        Coroutine yHandle = null;
        var wait = new WaitForSeconds(frequency);

        while(true)
        {
            if(xHandle != null) StopCoroutine(xHandle);
            if(yHandle != null) StopCoroutine(yHandle);

            xHandle = StartCoroutine(CurvePath(ref x,frequency));
            yHandle = StartCoroutine(CurvePath(ref y,frequency));

            yield return wait;
       }
    }

    private IEnumerator CurvePath(ref float curve, float duration)
    {
        // x - Get current value of CurvatureX
        float start = curve;
        float end = Random.Range(-50.0f, 50.0f);
        float lerp = 0;

        while (lerp<1 && duration>0)
        {
                lerp = Mathf.MoveToward(lerp,1, Time.deltaTime / duration);
                curve = Mathf.Lerp(start, end, lerp);
                yield return null;
        }
        
        curve = end;
    }
1 Like

No problem. Glad I could help.

1 Like