Search Unity

Mathf.Lerp

Discussion in 'Scripting' started by jister, Apr 30, 2013.

  1. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    I must be going blind, but this is not working for some reason?
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class fogcontrol : MonoBehaviour {
    5.  
    6.     public float speed = 2.0f;
    7.     private bool fading;
    8.     private GlobalFog fogCtrl;
    9.     private float fade=3.0f;
    10.     void Start ()
    11.     {
    12.         fogCtrl=GetComponent<GlobalFog>();
    13.     }
    14.     // Update is called once per frame
    15.     void Update ()
    16.     {
    17.         if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
    18.             fading = true;
    19.         if(fading)
    20.         {
    21.         fade= Mathf.Lerp(40.0f, 0.35f, Time.deltaTime * speed);
    22.             fogCtrl.startDistance=fade;
    23.         }
    24.         if(fogCtrl.startDistance <0.4f)
    25.             fading=false;
    26.        
    27.         print (fade +" "+fading);
    28.     }
    29. }
     
  2. EliteMossy

    EliteMossy

    Joined:
    Dec 2, 2012
    Posts:
    513
    You are always lerping from 40.0f i am sure.

    Ignore, the doc's seem to be confusing.
     
    Last edited: Apr 30, 2013
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Your code can't work like that; the third parameter in Lerp is a float between 0 and 1. If it's 0, then the first parameter is returned, if it's 1 then the second parameter is returned, and if it's between 0 and 1 then a proportional mix of the first and second parameters are returned. Since Time.deltaTime * speed is probably a quite small number, the result in this case will always be close to 40.0.

    --Eric
     
  4. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    I used the same method in a JS script and there is works?
    I thought the 3 param was kind of the speed to interpolate between the two?
    so i should make a counter form 0 to 1? is that the right approach?
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It could never work like that in any language; you did something differently.

    Nope, see the docs. Lerp is a simple math function (specifically, (1 - c)*b + c*a, where c is clamped between 0 and 1) that returns a value immediately; it doesn't run over time or anything.

    Yes. Coroutines are helpful for this, rather than using Update.

    --Eric
     
  6. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    thanks Eric
    this is the JS:
    Code (csharp):
    1. #pragma strict
    2.  
    3. var CLights:Light[];
    4. var intensity=1.0;
    5. var fog_Density=0.5;
    6. var fadingSpeed=2.0;
    7. var fading=false;
    8.  
    9. function OnTriggerEnter (collider:Collider)
    10. {
    11.     for(var L in CLights)
    12.     L.light.intensity=intensity;
    13.     RenderSettings.fogDensity=0.01;
    14.     fading=true;
    15. }
    16.  
    17. function Update ()
    18. {
    19.    
    20.     if(fading)
    21.     {
    22.         var fade=Mathf.Lerp(CLights[0].light.intensity, 0.0, Time.deltaTime*fadingSpeed);
    23.         for(var L in CLights)
    24.         L.light.intensity=fade;
    25.        
    26.         var fogIncrease=Mathf.Lerp(RenderSettings.fogDensity, fog_Density, Time.deltaTime*fadingSpeed);
    27.         RenderSettings.fogDensity=fogIncrease;
    28.     }
    29.     if(fade<0.1)
    30.         fading=false;
    31. }
     
  7. mweldon

    mweldon

    Joined:
    Apr 19, 2010
    Posts:
    109
    The JS function works because CLights[0].light.intensity serves as your accumulator. You modify it during every update. In the first script you have no accumulator.

    Also, I would point out that your JS function is not going to fade linearly. It is going to slow down as it approaches black.
     
  8. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    ok thanks for the explanation, i guess i had the wrong idea about Lerp although i read and understand the docs and the unity answer reply from eric before... is there a function that does (from: float, to: float, speed:float) ?
    or do i just use coroutines for these always?
     
  9. EliteMossy

    EliteMossy

    Joined:
    Dec 2, 2012
    Posts:
    513
    You should use co-routines or some sort of timing system
     
  10. CahMan

    CahMan

    Joined:
    Apr 3, 2013
    Posts:
    53
    Hey Guys,

    I would add that, if you are doing lots of Lerping, or you would like to extend functionality (like pausing), making a class around Lerp will get you a lot of mileage. A barebones example:

    Code (csharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class Lerper{
    7.    
    8.     bool _isLerping = false;
    9.     public bool IsLerping {get {return _isLerping;} set{}}
    10.    
    11.     bool _isPaused = false;
    12.     public bool IsPaused {get {return _isPaused;} set{}}
    13.    
    14.     float _lerpVal;
    15.     public float LerpVal {get {return _lerpVal;} set{}}
    16.    
    17.     float accumulator = 0f;
    18.    
    19.        
    20.     public IEnumerator Lerp(float start, float finish, float rate = 1f)
    21.     {
    22.         _isLerping = true;
    23.         while(accumulator < 1)
    24.         {
    25.             if( _isPaused == false)
    26.             {
    27.                 accumulator += Time.deltaTime * rate;
    28.                 _lerpVal = Mathf.Lerp(start, finish, accumulator);
    29.             }
    30.             yield return null;
    31.         }
    32.         _isLerping = false;
    33.     }
    34.    
    35.    
    36.     public void StopLerp()
    37.     {
    38.         accumulator = 1;
    39.     }
    40.    
    41.     public void Pause()
    42.     {
    43.         _isPaused = true;
    44.     }
    45.    
    46.     public void Unpause()
    47.     {
    48.         _isPaused = false;
    49.     }
    50.    
    51. }
    52.  
    This class could be easily extended to use delegates, handle events, etc, but may be overkill depending on your application.
     
  11. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    hey CahMan! again thanks for your input, that sure is handy to have!
    i just needed to do a small lerp so i ended up doing this:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class fogcontrol : MonoBehaviour {
    5.  
    6.     public float smooth = 2.0f;
    7.     public float startDistMin=0.0f;
    8.     public float startDistMax=50.0f;
    9.     private bool fading;
    10.     private GlobalFog fogCtrl;
    11.     private float fade=0.0f;
    12.     private float timer=0.0f;
    13.     void Start ()
    14.     {
    15.         fogCtrl=GetComponent<GlobalFog>();
    16.     }
    17.     // Update is called once per frame
    18.     void Update ()
    19.     {
    20.         if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
    21.             fading = true;
    22.         if(fading)
    23.         {
    24.             timer += Time.deltaTime/smooth;
    25.             fade= Mathf.Lerp(startDistMax, startDistMin, timer);
    26.             fogCtrl.startDistance=fade;
    27.         }
    28.         if(fogCtrl.startDistance <0.1f)
    29.         {
    30.             fading=false;
    31.             timer=0.0f;
    32.         }
    33.         print (fade +" "+fading);
    34.     }
    35. }