轉載自CSDN游一法師;
有時,我們在做游戲時會發現有些跟隨動作不夠圓滑或者需要一個緩沖的效果,這時,一般會考慮到插值。所以對插值的理解是必需的。(比如攝像機跟隨主角)
插值是數學上的一個概念,在這里用公式表示就是:from + (to - from) * t;這也就是Lerp的返回值(用這個公式分別算出x,y,z)。
static function Lerp (from : Vector3, to : Vector3, t : float) : Vector3
from 是起始的位置,to是目標位置,按照數字t在from到to之間插值。
按照分數t在from到to之間插值。這是最常用的尋找一點沿一條線的兩個端點之間一些分數的方式(例如,在那些點之間逐漸移動一個對象)。這分數是在范圍[ 0…1]。t是夾在 [0…1]之間,當t = 0時,返回from,當t = 1時,返回to。當t = 0.5 返回from和to的中間點。
這句話比較難理解,下面舉個例子。
這和我們用公式算出來的如出一轍。現在我們再看一個具體的例子
//在1秒時間動畫位置移動從from開始到to結束。(這是官方的例子)
位置移動從start開始到end結束,這好理解,但是為什么是1秒呢?
Time.time是從0開始隨時間增加的。
例1的t是一個固定的值,返回一個固定的向量。此時t是變量,在不斷增加。那么:
當Time.time = 0時--->transform.position = start.position,位置沒有變化;
當Time.time從0趨向於1時--->transform.position 不斷接近start.position,該腳本是掛在start物體上的,所以start會不斷靠近end。
那么問題來了,當Time.time>1的時候,會怎么樣呢?額(⊙o⊙)…我們說不會。
由上面的公式from + (to - from) * t可知,當t=1時,to - from = 0,此時t就無效了。
例1是從靜態角度看,例2是從動態角度看的(兩個變量,一個是時間在變化,一個是位置在變化)。
想一想例2,如果不是Time.time,而是0.5,會怎么樣?(只看一個變量)
-----這里的start.position如果是個初始定值,那么明顯只會移動到一半出,如果換成transform.position,才會如下圖速度逐漸減小的緩沖至終點;
由圖易知:A物體會不斷以0.5的比例無限接近於B----In fact,由於數據是有限位數的(如float),Unity中是可以取得B點位置的
如果上面都理解了,那么看官方的第二個例子就沒什么問題了,試一試吧!
//像彈簧一樣跟隨目標物體
public class testlerp : MonoBehaviour { private Vector3 des = new Vector3(-16, 1, 1); Vector3 start = new Vector3(1, 1, 1), end = new Vector3(2, 2, 2); Vector3 result; Vector3 start1; // Use this for initialization void Start () { start1 = this.transform.position; } // Update is called once per frame void Update () { result = Vector3.Lerp(start,end,0.5f); Debug.Log($"{result}"); //transform.position = Vector3.Lerp(start1,des,0.5f); transform.position = Vector3.Lerp(transform.position, des, Time.fixedDeltaTime*5); } }
此時官網的案列,以速度speed勻速走完全程:放在FixedUpdate()中最好
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { public Transform startMarker; public Transform endMarker; public float speed = 1.0F; private float startTime; private float journeyLength; public Transform target; public float smooth = 5.0F; void Start() { startTime = Time.time; journeyLength = Vector3.Distance(startMarker.position, endMarker.position); } void Update() { float distCovered = (Time.time - startTime) * speed; float fracJourney = distCovered / journeyLength; transform.position = Vector3.Lerp(startMarker.position, endMarker.position, fracJourney); } }