Search Unity

help to build exponential easing out curve

Discussion in 'Scripting' started by Sylon87, Jun 26, 2019.

  1. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    hi

    i'm trying to make an exponential ease out curve that will decelerate over time but start fast, and i need to clamp it on 0-1 range, anyone can help me to figure out how to make it?


    this is what i have

    Code (CSharp):
    1.          _currentLerpTime += in_deltatime;
    2.         float t = _currentLerpTime / _totalRotationTime;
    3.  
    4.         // disegna una curva chiusa
    5.         t = Mathf.Sin(t * Mathf.PI * 0.5f);
    6.  
    7.         /// applica la rotazione all'oggetto
    8.         Quaternion newRot
    9.                     = QuaternionExtension.Lerp(_startRotation,_requestedRotation,t,false);
    10.  
    11.         Vector3 current = newRot.eulerAngles;
    12.        
    13.         _currentAngle = current.x;
    14.  
    15.         _myCharacter.transform.localRotation
    16.                                         = newRot;
    17.        

    but doesn't start fast...
     
    Last edited: Jun 26, 2019
  2. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    Antistone likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    Wow, great visual easing resources @tonemcbride ! Thanks!

    Also, to the OP, check for tweening tools in the Unity Asset Store. A lot of them have built-in easing functions of varying complexity and configurability.
     
  4. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196

    thank's you for your resources!
    actually i found the one i looked for is this
    Code (CSharp):
    1. Math.easeInOutExpo = function (t, b, c, d) {
    2.     t /= d/2;
    3.     if (t < 1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
    4.     t--;
    5.     return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
    6. };
    but it will take four paremeter and didn't explain what they do..
     
  5. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    't' is the start time and 'd' is the duration. For that you can just assume 't' is between 0 and 1 and 'd' = 1

    'b' is the start value and 'c' is the value change.

    For example, if you were using it to move a sprite from X=50 to X=120 then 'b' would be 50 and 'c' would be 70 (120-50)
     
  6. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    so.. for my case b and c will be 0 and 1 because i'm looking to use it on a lerp as time right? where t will be deltatime, and d the duration of it i suppose..
     
    tonemcbride likes this.
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    If you want to call an ease like a lerp you'd do it like so (where t is between 0-1):
    Code (csharp):
    1.  
    2. public static float EasedLerp(Ease ease, float from, float to, float t)
    3. {
    4.     return ease(t, from, to - from, 1f);
    5. }
    6.  
    https://github.com/lordofduct/space...-3.0/blob/master/SPTween/Tween/Easing.cs#L395

    Mind you this method is based on if the ease method follows this specific shape:
    Code (csharp):
    1.  
    2. /// <summary>
    3. /// Represents an eased interpolation w/ respect to time.
    4. ///
    5. /// float t, float b, float c, float d
    6. /// </summary>
    7. /// <param name="current">how long into the ease are we</param>
    8. /// <param name="initialValue">starting value if current were 0</param>
    9. /// <param name="totalChange">total change in the value (not the end value, but the end - start)</param>
    10. /// <param name="duration">the total amount of time (when current == duration, the returned value will == initial + totalChange)</param>
    11. /// <returns></returns>
    12. public delegate float Ease(float current, float initialValue, float totalChange, float duration);
    13.  
    Which it appears the one Sylon87 posted does.

    The link to github I supplied above includes tons of easing methods, and in the description of it I tell you that you can see visual representations of them all by visiting msdn here:
    https://msdn.microsoft.com/en-us/library/vstudio/Ee308751(v=VS.100).aspx
     
  8. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    Yes, that sounds right to me.
     
  9. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    You could use AnimationCurve and just draw one in the inspector, then use Evaluate.

    Code (csharp):
    1. public AnimationCurve curve;
     
    halley likes this.
  10. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196

    already did it, but i 'm here to learn :)
     
  11. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    this is what i have now


    Code (CSharp):
    1.          _currentLerpTime += in_deltatime;
    2.         float t = _currentLerpTime / _totalRotationTime;
    3.  
    4.  
    5.         float time = EasedLerp(CURVE_START_VALUE,_totalRotationTime,_currentLerpTime);
    and this is what i'm using

    Code (CSharp):
    1.     private float CruveTime(
    2.         float in_time,
    3.         float in_initialValue,
    4.         float in_totalChange,
    5.         float in_duration)
    6.     {
    7.         return in_totalChange
    8.                         * ((in_time = in_time / in_duration - 1)
    9.                                             * in_time * in_time * in_time * in_time + 1)
    10.                                                                                 + in_initialValue;
    11.     }
    12.  
    13.     private float EasedLerp(float from, float to, float t)
    14.     {
    15.         return CruveTime(t, from, to - from, 1f);
    16.     }
    actually is too fast... what i'm doing wrong?
     
  12. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    You seem to be passing '_currentLerpTime' as the last parameter to EasedLerp rather than passing the 't' value you just created. Maybe that's the issue?
     
  13. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196

    i just tried with both.. will be slower but not as it should be...
     
  14. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    You also pass '_totalRotationTime' as the 'to' value. I think that should be 'CURVE_START_VALUE+_totalRotationTime'. That wouldn't matter though if CURVE_START_VALUE was 0.
     
  15. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    i also tried to put just 1, no changes... i just want that it will take fr example 4 seconds to get from 0 to 1..but no way to make it work..
     
  16. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    Code (CSharp):
    1.  
    2. _currentLerpTime += in_deltatime;
    3.  
    4. // 't' will go from 0 to 1 over a period of 4 seconds
    5. float t = Mathf.Clamp( _currentLerpTime / 4.0f , 0.0f , 1.0f );
    6.  
    7. // Lerp between 0 and 1 using 't'
    8. float time = EasedLerp(0.0f,1.0f,t);
    That's odd, I'm not sure what it could be. The above code should take 4 seconds to go from 0 to 1 if you want to try it out.
     
  17. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    well, it is clamped now, but doesn't have the curve motion, is going at the same speed

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5.  
    6. public class movecube : MonoBehaviour
    7. {
    8.     public float _totalLerpTime;
    9.    
    10.     private float _currentLerpTime;
    11.     private Vector3 start;
    12.  
    13.     private Vector3 end = new Vector3(0f,0.0f,150.0f);
    14.  
    15.     protected void Start() {
    16.  
    17.         start = Vector3.zero;
    18.  
    19.     }
    20.     protected void Update() {
    21.        
    22.         _currentLerpTime += Time.deltaTime;
    23.         Debug.Log(_currentLerpTime);
    24.         if(_currentLerpTime >= _totalLerpTime)
    25.         {
    26.             _currentLerpTime = _totalLerpTime;
    27.         }
    28.  
    29.         float t = Mathf.Clamp( _currentLerpTime / _totalLerpTime , 0.0f , 1.0f );
    30.  
    31.         float time = EasedLerp(0.0f,1.0f,t);
    32.  
    33.         Quaternion newRot = Quaternion.Lerp(Quaternion.Euler(start),Quaternion.Euler(end),t);
    34.  
    35.         transform.rotation = newRot;
    36.  
    37.         if(Input.GetKey(KeyCode.Space))
    38.         {
    39.             _currentLerpTime = 0.0f;
    40.         }
    41.     }
    42.     private float CruveTime(
    43.         float in_time,
    44.         float in_initialValue,
    45.         float in_totalChange,
    46.         float in_duration)
    47.     {
    48.         return in_totalChange
    49.                         * ((in_time = in_time / in_duration - 1)
    50.                                             * in_time * in_time * in_time * in_time + 1)
    51.                                                                                 + in_initialValue;
    52.     }
    53.     private float EasedLerp(float from, float to, float t)
    54.     {
    55.         return CruveTime(t, from, to - from, 1f);
    56.     }
    57. }
     
  18. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    well i found this good tutorial



    and following it i was able to create a smothstart and smothstop function.. smothstart is working well, but smothstop is working exactly as smothstart... i'm confused...

    Code (CSharp):
    1.         _currentLerpTime += Time.deltaTime;
    2.         // Debug.Log(_currentLerpTime);
    3.         if(_currentLerpTime >= _totalLerpTime)
    4.         {
    5.             _currentLerpTime = _totalLerpTime;
    6.         }
    7.  
    8.         float t = _currentLerpTime / _totalLerpTime;
    9.  
    10.         float time = SmothStop(t);
    11.  
    12.  
    13.  
    14.  
    15.         Quaternion newRot = Quaternion.Lerp(Quaternion.Euler(start),Quaternion.Euler(end),time);
    16.  
    17.         transform.rotation = newRot;
    18.  

    here SmothStop Function

    Code (CSharp):
    1.     private float SmothStop(float t)
    2.     {
    3.         float time = 1 - (1 - t * t * t * t * t);
    4.         return time;
    5.     }
     
  19. Sylon87

    Sylon87

    Joined:
    Aug 20, 2018
    Posts:
    196
    fixed... for anyone that is looking to the same thing, here my solution

    Code (CSharp):
    1.     private float SmothStop2(float t)
    2.     {
    3.         float s = 1f - t;
    4.  
    5.         return 1 - s * s * s * s * s * s;
    6.     }