Search Unity

Mathf.Lerp help required

Discussion in 'Scripting' started by Deleted User, May 26, 2017.

  1. Deleted User

    Deleted User

    Guest

    Hi,

    I have the following snippet of code :

    Code (CSharp):
    1.     void changePathCurvature()
    2.     {
    3.         // x - Get current value of CurvatureX
    4.         currentCurvatureX = x;
    5.  
    6.         // newCurvatureX = Random within a range of -50 and 50
    7.         newCurvatureX = (Random.Range(-50.0f, 50.0f));
    8.  
    9.         // x = Lerp currentCurvatureX to newCurvatureX over timeInterval
    10.         x = Mathf.Lerp(currentCurvatureX, newCurvatureX, timeInterval);
    11.  
    12.         // y - Get current value of CurvatureY
    13.         currentCurvatureY = y;
    14.  
    15.         // newCurvatureY = Random within a range of -50 and 50
    16.         newCurvatureY = (Random.Range(-50.0f, 50.0f));
    17.  
    18.         // y = Lerp currentCurvatureY to newCurvatureY over timeInterval
    19.         y = Mathf.Lerp(currentCurvatureY, newCurvatureY, timeInterval);
    20.     }
    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.
     
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    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.
     
    Deleted User likes this.
  3. sylon

    sylon

    Joined:
    Mar 5, 2017
    Posts:
    246
    This is a cool article about the subject : link
     
    Deleted User likes this.
  4. Deleted User

    Deleted User

    Guest

    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

    Code (CSharp):
    1. void Start ()
    2. {
    3.     // Other stuff here....
    4.  
    5.     InvokeRepeating("changePathCurvature", timeInterval, timeInterval);
    6. }
    and my code as posted before :

    Code (CSharp):
    1. void changePathCurvature()
    2.     {
    3.         // x - Get current value of CurvatureX
    4.         currentCurvatureX = x;
    5.  
    6.         // newCurvatureX = Random within a range of -50 and 50
    7.         newCurvatureX = (Random.Range(-50.0f, 50.0f));
    8.  
    9.         // x = Lerp currentCurvatureX to newCurvatureX over timeInterval
    10.         x = Mathf.Lerp(currentCurvatureX, newCurvatureX, timeInterval);
    11.  
    12.         // y - Get current value of CurvatureY
    13.         currentCurvatureY = y;
    14.  
    15.         // newCurvatureY = Random within a range of -50 and 50
    16.         newCurvatureY = (Random.Range(-50.0f, 50.0f));
    17.  
    18.         // y = Lerp currentCurvatureY to newCurvatureY over timeInterval
    19.         y = Mathf.Lerp(currentCurvatureY, newCurvatureY, timeInterval);
    20.     }
    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 ? :(
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    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.
     
    Deleted User likes this.
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    You could change the entire thing into a Coroutine:
    Code (csharp):
    1.  
    2. IEnumerator MyLerp(){
    3.    // This should work just like InvokeRepeating
    4.    while(true) {
    5.       float startval = startingval;
    6.       float endval = endingval;
    7.       float runtime = 30;
    8.       float t = 0;
    9.       for(t = 0; t <= runtime; t+=time.deltaTime) {
    10.          whateverVar = Mathf.Lerp(startval, endval, t / runtime);
    11.          yield return null;
    12.        }
    13.       // maybe set to end value here if it's not exact?
    14.    }
    15. }
    16.  
    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.
     
    Last edited: May 27, 2017
    Deleted User likes this.
  7. Deleted User

    Deleted User

    Guest

    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 ! :) :oops:
     
  8. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    Sylon posted a great article about how Lerp works and how its often misused.

    This is the formula for Lerp:

    Code (CSharp):
    1. public float Lerp( float a, float b, float percent)
    2. {
    3.     percent = Mathf.Clamp(percent, 0, 1); // clamps percent to always be between 0~1
    4.  
    5.     return b*percent + a*(1-percent);
    6.  
    7. }
    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
    Code (CSharp):
    1.  
    2.     private void Start()
    3.     {
    4.         StartCoroutine(ChangeCurvePath(30.0));//change the curve every 30 seconds
    5.     }
    6.  
    7.     private IEnumerator ChangeCurvePath(float frequency)
    8.     {
    9.         Coroutine xHandle = null;
    10.         Coroutine yHandle = null;
    11.         var wait = new WaitForSeconds(frequency);
    12.  
    13.         while(true)
    14.         {
    15.             if(xHandle != null) StopCoroutine(xHandle);
    16.             if(yHandle != null) StopCoroutine(yHandle);
    17.  
    18.             xHandle = StartCoroutine(CurvePath(ref x,frequency));
    19.             yHandle = StartCoroutine(CurvePath(ref y,frequency));
    20.  
    21.             yield return wait;
    22.        }
    23.     }
    24.  
    25.     private IEnumerator CurvePath(ref float curve, float duration)
    26.     {
    27.         // x - Get current value of CurvatureX
    28.         float start = curve;
    29.         float end = Random.Range(-50.0f, 50.0f);
    30.         float lerp = 0;
    31.  
    32.         while (lerp<1 && duration>0)
    33.         {
    34.                 lerp = Mathf.MoveToward(lerp,1, Time.deltaTime / duration);
    35.                 curve = Mathf.Lerp(start, end, lerp);
    36.                 yield return null;
    37.         }
    38.        
    39.         curve = end;
    40.     }
    41.  
     
    Deleted User likes this.
  9. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    No problem. Glad I could help.
     
    Deleted User likes this.