help to build exponential easing out curve

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

         _currentLerpTime += in_deltatime;
        float t = _currentLerpTime / _totalRotationTime;

        // disegna una curva chiusa
        t = Mathf.Sin(t * Mathf.PI * 0.5f);

        /// applica la rotazione all'oggetto
        Quaternion newRot
                    = QuaternionExtension.Lerp(_startRotation,_requestedRotation,t,false);

        Vector3 current = newRot.eulerAngles;
       
        _currentAngle = current.x;

        _myCharacter.transform.localRotation
                                        = newRot;

but doesn’t start fast…

There’s quite a few that I’ve used here: Easing Equations

They might be useful?

I also use this Easing Functions Cheat Sheet as a good way to visualise what I’m looking for.

1 Like

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.

thank’s you for your resources!
actually i found the one i looked for is this

Math.easeInOutExpo = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
    t--;
    return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
};

but it will take four paremeter and didn’t explain what they do…

‘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)

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…

1 Like

If you want to call an ease like a lerp you’d do it like so (where t is between 0-1):

public static float EasedLerp(Ease ease, float from, float to, float t)
{
    return ease(t, from, to - from, 1f);
}

Mind you this method is based on if the ease method follows this specific shape:

/// <summary>
/// Represents an eased interpolation w/ respect to time.
///
/// float t, float b, float c, float d
/// </summary>
/// <param name="current">how long into the ease are we</param>
/// <param name="initialValue">starting value if current were 0</param>
/// <param name="totalChange">total change in the value (not the end value, but the end - start)</param>
/// <param name="duration">the total amount of time (when current == duration, the returned value will == initial + totalChange)</param>
/// <returns></returns>
public delegate float Ease(float current, float initialValue, float totalChange, float duration);

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:

Yes, that sounds right to me.

You could use AnimationCurve and just draw one in the inspector, then use Evaluate.

public AnimationCurve curve;
1 Like

already did it, but i 'm here to learn :slight_smile:

this is what i have now

         _currentLerpTime += in_deltatime;
        float t = _currentLerpTime / _totalRotationTime;


        float time = EasedLerp(CURVE_START_VALUE,_totalRotationTime,_currentLerpTime);

and this is what i’m using

    private float CruveTime(
        float in_time,
        float in_initialValue,
        float in_totalChange,
        float in_duration)
    {
        return in_totalChange
                        * ((in_time = in_time / in_duration - 1)
                                            * in_time * in_time * in_time * in_time + 1)
                                                                                + in_initialValue;
    }

    private float EasedLerp(float from, float to, float t)
    {
        return CruveTime(t, from, to - from, 1f);
    }

actually is too fast… what i’m doing wrong?

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?

i just tried with both… will be slower but not as it should be…

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.

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…

_currentLerpTime += in_deltatime;

// 't' will go from 0 to 1 over a period of 4 seconds
float t = Mathf.Clamp( _currentLerpTime / 4.0f , 0.0f , 1.0f );
  
// Lerp between 0 and 1 using 't'
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.

well, it is clamped now, but doesn’t have the curve motion, is going at the same speed

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class movecube : MonoBehaviour
{
    public float _totalLerpTime;
   
    private float _currentLerpTime;
    private Vector3 start;

    private Vector3 end = new Vector3(0f,0.0f,150.0f);

    protected void Start() {

        start = Vector3.zero;

    }
    protected void Update() {
       
        _currentLerpTime += Time.deltaTime;
        Debug.Log(_currentLerpTime);
        if(_currentLerpTime >= _totalLerpTime)
        {
            _currentLerpTime = _totalLerpTime;
        }

        float t = Mathf.Clamp( _currentLerpTime / _totalLerpTime , 0.0f , 1.0f );

        float time = EasedLerp(0.0f,1.0f,t);

        Quaternion newRot = Quaternion.Lerp(Quaternion.Euler(start),Quaternion.Euler(end),t);

        transform.rotation = newRot;

        if(Input.GetKey(KeyCode.Space))
        {
            _currentLerpTime = 0.0f;
        }
    }
    private float CruveTime(
        float in_time,
        float in_initialValue,
        float in_totalChange,
        float in_duration)
    {
        return in_totalChange
                        * ((in_time = in_time / in_duration - 1)
                                            * in_time * in_time * in_time * in_time + 1)
                                                                                + in_initialValue;
    }
    private float EasedLerp(float from, float to, float t)
    {
        return CruveTime(t, from, to - from, 1f);
    }
}

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…

        _currentLerpTime += Time.deltaTime;
        // Debug.Log(_currentLerpTime);
        if(_currentLerpTime >= _totalLerpTime)
        {
            _currentLerpTime = _totalLerpTime;
        }

        float t = _currentLerpTime / _totalLerpTime;

        float time = SmothStop(t);




        Quaternion newRot = Quaternion.Lerp(Quaternion.Euler(start),Quaternion.Euler(end),time);

        transform.rotation = newRot;

here SmothStop Function

    private float SmothStop(float t)
    {
        float time = 1 - (1 - t * t * t * t * t);
        return time;
    }

fixed… for anyone that is looking to the same thing, here my solution

    private float SmothStop2(float t)
    {
        float s = 1f - t;

        return 1 - s * s * s * s * s * s;
    }