{"id":404,"date":"2014-02-08T15:09:52","date_gmt":"2014-02-08T20:09:52","guid":{"rendered":"http:\/\/www.blueraja.com\/blog\/?p=404"},"modified":"2016-10-03T15:44:30","modified_gmt":"2016-10-03T21:44:30","slug":"how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly","status":"publish","type":"post","link":"https:\/\/www.blueraja.com\/blog\/404\/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly","title":{"rendered":"Using Vector3.Lerp() correctly in Unity"},"content":{"rendered":"<p>A lot of Unity 3D tutorials online use Unity\u2019s linear interpolation incorrectly, including <a href=\"http:\/\/unity3d.com\/learn\/tutorials\/modules\/beginner\/scripting\/lerp\">the official video tutorials<\/a>(!). However, it\u2019s actually very easy to use, once you understand how it works.<\/p>\n<p>The prototype for `Vector3.Lerp` looks like this<\/p>\n<p><span class=\"lang:c# decode:true crayon-inline \">static Vector3 Lerp(Vector3 start, Vector3 finish, float percentage)<\/span><\/p>\n<p>What it does is simple: it returns a point between start and finish, based on the value of `percentage`:<\/p>\n<ul>\n<li>At `percentage = 0.0`, `Lerp()` returns `start`<\/li>\n<li>At `percentage = 1.0`, `Lerp()` returns `finish`<\/li>\n<li>At `0.0 &lt; percentage &lt; 1.0`, `Lerp()` returns a point between `start` and `finish`.<\/li>\n<li>\u00a0\u00a0 So at `percentage = 0.5`, it returns the point exactly halfway between `start` and `finish`.<\/li>\n<li>\u00a0\u00a0 And at `percentage = 0.10`, it returns a point very near to `start`<\/li>\n<\/ul>\n<p>etc.<\/p>\n<p><a href=\"http:\/\/www.blueraja.com\/blog\/wp-content\/uploads\/2014\/02\/Lerp.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-407\" src=\"http:\/\/www.blueraja.com\/blog\/wp-content\/uploads\/2014\/02\/Lerp.png\" alt=\"Linear Interpolation Example\" width=\"677\" height=\"446\" srcset=\"https:\/\/www.blueraja.com\/blog\/wp-content\/uploads\/2014\/02\/Lerp.png 800w, https:\/\/www.blueraja.com\/blog\/wp-content\/uploads\/2014\/02\/Lerp-300x198.png 300w\" sizes=\"(max-width: 677px) 100vw, 677px\" \/><\/a><\/p>\n<p>This explains why it\u2019s called linear interpolation: It moves smoothly (interpolates) at a constant speed (linearly) between two points!<\/p>\n<h2>How to use Lerp correctly<\/h2>\n<p>To use `Lerp()` correctly, you simply have to make sure that you <strong>pass the same `start` and `finish` values every frame<\/strong> while moving percentage up from 0.0 to 1.0 each frame.<\/p>\n<p>Here\u2019s an example. When the spacebar is pressed, we\u2019ll lerp our object 10 spaces forward over a period of 1 second.<\/p>\n<pre class=\"lang:c# decode:true \" title=\"LerpOnSpacebarScript\">using UnityEngine;\r\nusing System.Collections;\r\n\r\npublic class LerpOnSpacebarScript : MonoBehaviour\r\n{\r\n\t\/\/\/ &lt;summary&gt;\r\n\t\/\/\/ The time taken to move from the start to finish positions\r\n\t\/\/\/ &lt;\/summary&gt;\r\n\tpublic float timeTakenDuringLerp = 1f;\r\n\r\n\t\/\/\/ &lt;summary&gt;\r\n\t\/\/\/ How far the object should move when 'space' is pressed\r\n\t\/\/\/ &lt;\/summary&gt;\r\n\tpublic float distanceToMove = 10;\r\n\r\n\t\/\/Whether we are currently interpolating or not\r\n\tprivate bool _isLerping;\r\n\r\n\t\/\/The start and finish positions for the interpolation\r\n\tprivate Vector3 _startPosition;\r\n\tprivate Vector3 _endPosition;\r\n\r\n\t\/\/The Time.time value when we started the interpolation\r\n\tprivate float _timeStartedLerping;\r\n\r\n\t\/\/\/ &lt;summary&gt;\r\n\t\/\/\/ Called to begin the linear interpolation\r\n\t\/\/\/ &lt;\/summary&gt;\r\n\tvoid StartLerping()\r\n\t{\r\n\t\t_isLerping = true;\r\n\t\t_timeStartedLerping = Time.time;\r\n\r\n\t\t\/\/We set the start position to the current position, and the finish to 10 spaces in the 'forward' direction\r\n\t\t_startPosition = transform.position;\r\n\t\t_endPosition = transform.position + Vector3.forward*distanceToMove;\r\n\t}\r\n\r\n\tvoid Update()\r\n\t{\r\n\t\t\/\/When the user hits the spacebar, we start lerping\r\n\t\tif(Input.GetKey(KeyCode.Space))\r\n\t\t{\r\n\t\t\tStartLerping();\r\n\t\t}\r\n\t}\r\n\r\n\t\/\/We do the actual interpolation in FixedUpdate(), since we're dealing with a rigidbody\r\n\tvoid FixedUpdate()\r\n\t{\r\n\t\tif(_isLerping)\r\n\t\t{\r\n\t\t\t\/\/We want percentage = 0.0 when Time.time = _timeStartedLerping\r\n\t\t\t\/\/and percentage = 1.0 when Time.time = _timeStartedLerping + timeTakenDuringLerp\r\n\t\t\t\/\/In other words, we want to know what percentage of \"timeTakenDuringLerp\" the value\r\n\t\t\t\/\/\"Time.time - _timeStartedLerping\" is.\r\n\t\t\tfloat timeSinceStarted = Time.time - _timeStartedLerping;\r\n\t\t\tfloat percentageComplete = timeSinceStarted \/ timeTakenDuringLerp;\r\n\r\n\t\t\t\/\/Perform the actual lerping.  Notice that the first two parameters will always be the same\r\n\t\t\t\/\/throughout a single lerp-processs (ie. they won't change until we hit the space-bar again\r\n\t\t\t\/\/to start another lerp)\r\n\t\t\ttransform.position = Vector3.Lerp (_startPosition, _endPosition, percentageComplete);\r\n\r\n\t\t\t\/\/When we've completed the lerp, we set _isLerping to false\r\n\t\t\tif(percentageComplete &gt;= 1.0f)\r\n\t\t\t{\r\n\t\t\t\t_isLerping = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<h2>How to use Lerp incorrectly<\/h2>\n<p>In our above example, we call `Vector3.Lerp()` like this:<\/p>\n<p><code>transform.position = Vector3.Lerp(_startPosition, _endPosition, percentageComplete);<\/code><\/p>\n<p>However, the method for calling Lerp you see in many tutorials online looks like this:<\/p>\n<p><code>transform.position = Vector3.Lerp(transform.position, _endPosition, speed*Time.deltaTime);<\/code><\/p>\n<p>Before I explain what\u2019s wrong with this, please take a moment and try to figure out for yourself what this code will do, and why it\u2019s wrong<\/p>\n<p>\u2026<br \/>\n\u2026<br \/>\n&#8230;Ready?<\/p>\n<p>The issue with the above code is that <strong>the first parameter to `Lerp()`, `transform.position`, changes every frame!<\/strong> Additionally, the `percentage` parameter <em>(the third parameter)<\/em> does not increase from 0.0 to 1.0, but instead is set to the completely arbitrary value `speed*Time.deltaTime`.<\/p>\n<p>What this code actually does is move the object `speed*Time.deltaTime`-percent closer to `_endPosition` every frame.<\/p>\n<p>There are several problems with this.<\/p>\n<ol>\n<li><strong>It\u2019s non-linear<\/strong> ie. the speed is not constant. This is easy to see in <a href=\"http:\/\/www.youtube.com\/watch?v=cD-mXwSCvWc#t=02m42s\">the official video tutorial<\/a>; the object moves quickly at first, and slows down as it nears its destination<\/li>\n<li><strong>The object\u2019s speed varies with the user\u2019s framerate.<\/strong> The higher the user\u2019s framerate, the faster the object will move. This defeats the purpose of using `FixedUpdate()` to begin with, which is supposed to alleviate this problem.<\/li>\n<li><strong>The object never reaches its destination<\/strong> since we only move a percentage closer each frame. Actually, due to floating-point rounding, it may or may not ever reach its destination. Additionally, because of problem 2, whether or not it ever reaches its destination depends on the user\u2019s framerate. <strong> Ouch!<\/strong><\/li>\n<\/ol>\n<h2>The implementation of Lerp<\/h2>\n<p>As a final note, I\u2019d like to share how `Lerp()` is typically implemented. This section is not required, but mathematically-inclined readers will find it interesting.<\/p>\n<p>Implementing `Lerp()` is actually remarkably simple:<\/p>\n<pre class=\"lang:c# decode:true\">public static Vector3 Lerp(Vector3 start, Vector3 finish, float percentage)\r\n{\r\n    \/\/Make sure percentage is in the range [0.0, 1.0]\r\n    percentage = Mathf.Clamp01(percentage);\r\n\r\n    \/\/(finish-start) is the Vector3 drawn between 'start' and 'finish'\r\n    Vector3 startToFinish = finish - start;\r\n\r\n    \/\/Multiply it by percentage and set its origin to 'start'\r\n    return start + startToFinish * percentage;\r\n}<\/pre>\n<p><em>(Edit Oct 2016: A <a href=\"http:\/\/www.blueraja.com\/blog\/404\/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly#comment-23334\">commenter<\/a> correctly pointed out that this implementation of `Lerp()` has floating-point rounding issues. See his comment for a more accurate version)<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A lot of Unity 3D tutorials online use Unity\u2019s linear interpolation incorrectly, including the official video tutorials(!). However, it\u2019s actually very easy to use, once you understand how it works. The prototype for `Vector3.Lerp` looks like this static Vector3 Lerp(Vector3 start, Vector3 finish, float percentage) What it does is simple: it returns a point between [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts\/404"}],"collection":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/comments?post=404"}],"version-history":[{"count":45,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts\/404\/revisions"}],"predecessor-version":[{"id":546,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/posts\/404\/revisions\/546"}],"wp:attachment":[{"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/media?parent=404"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/categories?post=404"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blueraja.com\/blog\/wp-json\/wp\/v2\/tags?post=404"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}