# A smooth (ease in out) version of Lerp?

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

1. ### petey

Joined:
May 20, 2009
Posts:
1,827
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

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

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

### Volunteer ModeratorModerator

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

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:

• ###### \$easing_185.zip
File size:
4.6 KB
Views:
2,041
herrkjeldsen_unity and oliran like this.
6. ### petey

Joined:
May 20, 2009
Posts:
1,827
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

### Volunteer ModeratorModerator

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

Joined:
May 20, 2009
Posts:
1,827
That worked perfect,
I actually triple embedded it! 0_o
Thanks again.

Blatticus likes this.
9. ### 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

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.

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.

Joined:
Feb 12, 2015
Posts:
1,742
13. ### 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

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

15. ### Alekazam

Joined:
Jun 27, 2022
Posts:
8
This works great!

16. ### halley

Joined:
Aug 26, 2013
Posts:
2,661
Use the "Like" button instead of dragging this ancient dead thread from 2009 up into everyone's feed.