Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

A smooth (ease in out) version of Lerp?

Discussion in 'Scripting' started by petey, Aug 12, 2009.

  1. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,817
    Hi there,
    I was using some code like this to move a camera from one position to another, but I can't figure out a way to get it to ease out and in of the movement. I realise that Lerp is Linear, but is there a way to get it to be smooth?

    I've looked into mathfx but im not sure how to use the hermite function with this code...

    Code (csharp):
    1.  
    2. var Startspot : Transform;
    3. var Midspot : Transform;
    4. var Endspot : Transform;
    5.  
    6. function Update () {
    7. transform.position = Vector3.Lerp(Startspot.position,Endspot.position,Time.time);
    8. }
    Thanks
    Pete
     
  2. GargerathSunman

    GargerathSunman

    Joined:
    May 1, 2008
    Posts:
    1,571
    Well, you could replace Time.time with a variable of your own and smooth it by hand.... 1 = at the other side, 0 = at the first side.
     
  3. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    Something like this should work:
    Code (csharp):
    1.  
    2. var time = Mathfx.Hermite(0.0, 1.0, Time.time);
    3. transform.position = Vector3.Lerp(Startspot.position,Endspot.position,time);
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The easiest thing is, don't use Update, use coroutines. Mathf.Smoothstep is useful too:

    Code (csharp):
    1. var startspot : Transform;
    2. var endspot : Transform;
    3.  
    4. function Start () {
    5.     SmoothMove(startspot.position, endspot.position, 5.0);
    6. }
    7.  
    8. function SmoothMove (startpos : Vector3, endpos : Vector3, seconds : float) {
    9.     var t = 0.0;
    10.     while (t <= 1.0) {
    11.         t += Time.deltaTime/seconds;
    12.         transform.position = Vector3.Lerp(startpos, endpos, Mathf.SmoothStep(0.0, 1.0, t));
    13.         yield;
    14.     }
    15. }
    --Eric
     
    Thincc, avacio, Joy-less and 7 others like this.
  5. robhuhn

    robhuhn

    Joined:
    Jun 21, 2009
    Posts:
    113
    you could use easingfunctions like this:

    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.     if (Time.time - timeStamp <= duration)
    5.         factor = (float)Cubic.easeInOut(Time.time - timeStamp, 0, 1, duration);
    6. }
    7.  
    8.  
    9. void FixedUpdate()
    10. {
    11.     Vector3 changePosition = startPosition + factor * (targetPosition - startPosition);
    12.     transform.localPosition = changePosition;
    13. }
    14.  
     

    Attached Files:

    herrkjeldsen_unity and oliran like this.
  6. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,817
    Hey thanks Guys!
    I ended up using Eric5h5's solution as it fitted best with what I was doing.
    That works great but I was wondering, is there a way to exaggerate the easing effect there?
    Thanks again!
    Pete
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Apply the smoothstep to itself again...maybe kind of cheesy, but should be effective:

    Code (csharp):
    1. transform.position = Vector3.Lerp(startpos, endpos, Mathf.SmoothStep(0.0, 1.0, Mathf.SmoothStep(0.0, 1.0, t)));
    --Eric
     
    kalinixk3, BAIZOR, Malbers and 2 others like this.
  8. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,817
    That worked perfect,
    I actually triple embedded it! 0_o
    Thanks again.
     
    Blatticus likes this.
  9. Charles-Van-Norman

    Charles-Van-Norman

    Joined:
    Aug 10, 2010
    Posts:
    86
    You could just use Sine of Time. Know how the Sine wave looks smooth? That's an ease-in out function. This is what I use:


    Code (CSharp):
    1.  
    2. float t =0;
    3. float duration = 2f;
    4. Transform from;
    5. Transform to;
    6. float moveSpeed = 0f;
    7. void Start(){
    8.         transform.position = from.position;
    9.         moveSpeed = Vector3.Distance(from.position, to.position);
    10. }
    11. void Update(){
    12.  
    13.     t += Time.deltaTime;
    14.     if (t < duration){
    15.         transform.position += -transform.up * Time.deltaTime * Mathf.Sin(t * Mathf.PI / duration) * moveSpeed/Mathf.PI * 2f;
    16.     }
    17. }
     
  10. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    If you want to be able to fine tune your interpolation function, you can use an AnimationCurve so you can edit the curve manually from the Inspector:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CustomInterpolation : MonoBehaviour
    5. {
    6.     public AnimationCurve curve = AnimationCurve.Linear(0.0f, 0.0f, 1.0f, 1.0f);
    7.     public Transform start;
    8.     public Transform end;
    9.     public float duration = 1.0f;
    10.     float t;
    11.     // Use this for initialization
    12.     void Start ()
    13.     {
    14.         t = 0.0f;
    15.     }
    16.  
    17.     // Update is called once per frame
    18.     void Update ()
    19.     {
    20.         t += Time.deltaTime;
    21.         float s = t / duration;
    22.         transform.position = Vector3.Lerp(start.position, end.position, curve.Evaluate(s));
    23.     }
    24. }
    25.  
    Doing the tweening yourself can be tedious, I suggest using an external tool. I'm really satisfied with DOTween:

    http://dotween.demigiant.com/

    It will make you code simpler and save you a lot of time:
    Code (CSharp):
    1. using UnityEngine;
    2. using DG.Tweening;
    3.  
    4. public class CustomInterpolation : MonoBehaviour
    5. {
    6.     public AnimationCurve curve = AnimationCurve.Linear(0.0f, 0.0f, 1.0f, 1.0f);
    7.     public Transform start;
    8.     public Transform end;
    9.     public float duration = 1.0f;
    10.  
    11.     // Use this for initialization
    12.     void Start ()
    13.     {
    14.         transform.DOMove(end.position, duration)
    15.             .ChangeStartValue(start.position)
    16.             .SetEase(curve);
    17.     }
    18. }
    19.  
     
  11. adavies25

    adavies25

    Joined:
    Nov 30, 2015
    Posts:
    1
    Thought I would share my move and rotate coroutine based on ericbegue's code above. Thanks for the share!

    Code (CSharp):
    1.    
    2.     public Transform m_playerTrans;
    3.     public AnimationCurve m_moveCurve = AnimationCurve.Linear(0.0f, 0.0f, 1.0f, 1.0f);
    4.     public float m_moveDuration = 1.0f;
    5.  
    6.     void DoMove()
    7.     {
    8.         StartCoroutine(MoveToPosition(m_playerTransform, destinationTransform, m_moveDuration));
    9.     }
    10.  
    11.     private IEnumerator MoveToPosition(Transform movingTrans, Transform moveToTrans, float duration)
    12.     {
    13.         float animationTime = 0;
    14.         var startPos = movingTrans.position;
    15.         var startRot = movingTrans.rotation;
    16.         var endPos = moveToTrans.position;
    17.         var endRot = moveToTrans.rotation;
    18.         var animationTimeLength = m_moveCurve[m_moveCurve.length - 1].time;
    19.  
    20.         while(animationTime < animationTimeLength)
    21.         {
    22.             animationTime += (Time.deltaTime / duration);
    23.             movingTrans.position = Vector3.Lerp(startPos, endPos, m_moveCurve.Evaluate(animationTime));
    24.             movingTrans.rotation = Quaternion.Slerp(startRot, endRot, m_moveCurve.Evaluate(animationTime));
    25.             yield return null;
    26.         }
    27.     }
     
    paulygons likes this.
  12. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
  13. drninja

    drninja

    Joined:
    Apr 13, 2017
    Posts:
    5
    Holy crap this helped me so much, being able to visually play with the curves in the inspector was a huge help for what I'm currently working on. Thanks!

     
    Shippety likes this.
  14. KarlKarl2000

    KarlKarl2000

    Joined:
    Jan 25, 2016
    Posts:
    606
    @ericbegue Love ya !!!

    As an artist, there's only so much nested calculations my brain can handle before it explodes.

    Your solution with Dotween and animation Curves is brilliant!

    Thanks alot