Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. On February 28th the Feedback website will shut down and be redirected to the Unity forums. See the full post for more information.
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Unity 2018.3 is now released.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    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,215
    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,572
    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:
    31,939
    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
     
  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,215
    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:
    31,939
    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
     
    Malbers, Ash-Blue and lexen1 like this.
  8. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,215
    That worked perfect,
    I actually triple embedded it! 0_o
    Thanks again.
     
  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,293
    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,470
  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!

     
  14. indieDoroid

    indieDoroid

    Joined:
    Jan 25, 2016
    Posts:
    124
    @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