----------------------轉(zhuǎn)自Unity Connect
介紹
在我看來,插值是設(shè)計中最酷的概念之一。如果您正在制作游戲,用戶界面或動畫,則無關(guān)緊要。沒有別的東西可以讓你在一小段變化的質(zhì)量方面獲得更大的收益。
當我第一次開始游戲開發(fā)時,我對這個想法很陌生,坦率地說,數(shù)學讓我感到害怕。它似乎很復雜,也是無法接近的,但實際上這個概念有多么簡單。一旦理解了基本原理,可能性就是無窮無盡的。
什么是插值?
Interpolation的核心是在兩個值之間創(chuàng)建新數(shù)據(jù)的行為。換句話說,允許您平穩(wěn)地從一個數(shù)字移動到另一個數(shù)字。在動畫示例中,您可以看到這些值可以是“ 位置” ,“ 可見性” 或“ 顏色”中的任何值。
基本
在我們想到任何想象之前,讓我們開始吧。我們來做一些超級基礎(chǔ)數(shù)學。
如果我給你3號,并說目標是10 ,你怎么到達那里?
你加7,對嗎?
讓我們將它們標記為開始,差異和目標。
簡而言之:
開始+差異=目標
(我知道,我知道......和我在一起)
這是有趣的地方。讓我再添加一個號碼,我們稱之為時間。這個新數(shù)字只會是0 到1 之間的某個數(shù)字。讓我們看看當我們改變公式時會發(fā)生什么。
開始+(差異*時間)=?
如果我們?yōu)闀r間傳遞0 ,我們得到.... 開始,但如果我們傳入1,我們得到目標。
還是很簡單吧?如果我們通過在....會發(fā)生什么0.5 ?我們在Start 和Goal 之間獲得了一半。
那......基本上就是它!你所擁有的是線性插值的整個概念。就實際代碼而言:
讓我們看看它的實際效果:
線性插值
</figure>
這是整個核心概念。
其他一切都建立在這個想法之上。要記住的重要一點是,未來唯一改變的是時間。(它只會在0 和1 之間)。
非線性插值
我們上面創(chuàng)建的是動作。在物理學術(shù)語中,你應(yīng)該看到與運動方程的相似性。在一天結(jié)束時,這就是我們正在做的事情,隨著時間的推移,我們正在從一個位置移動到另一個位置。
然而,上面的那種動作,坦率地說...... 無聊。它是線性的。它在同一時間傳播完全相同的距離。它需要相同的時間才能達到中途點,從中途到結(jié)束。
這不是現(xiàn)實生活中的動作。
在現(xiàn)實生活中,移動物品有加速度。汽車不會從無動作變?yōu)樵O(shè)定速度并立即停止。它坡道慢慢加快速度,臨近年底它會減慢。
我們?nèi)绾蔚玫轿覀兊牡仁侥兀坑米詈唵蔚男g(shù)語來說,我們改變時間。我們截取值Time 并在將它應(yīng)用于對象之前對其進行更改。我們來看一些代碼:
public float ValueSnap(float time)
{
if(time < 0.4f) return 0;
if(time > 0.6f) return 1;
else return 0.5f;
}
這個功能說的是什么; 無論你通過什么號碼,永遠只能返回0 ,0.5,或1。
如果我們將兩者結(jié)合起來:
[Range(0,1)]
float time = 0;
void Update()
{
var changedTime = ValueSnap(time);
var answer = Interpolate(3,10,changedTime);
}
讓我們看看這對我們的議案有何影響:
<figure class="" data-block="true" data-editor="editorBody" data-offset-key="vetf-0-0" contenteditable="false" style="display: block; box-sizing: border-box; max-width: 1000px; word-wrap: break-word; white-space: pre-wrap; margin: 0px auto 32px;">
快照插值
</figure>
雖然想想這意味著什么,但這并不是世界上最激動人心的事情。我們可以在0 和1 之間取一些值來表示已經(jīng)過了多少時間并且捏造數(shù)字,因此移動者處于轉(zhuǎn)換的不同百分比而不是實時。
在動畫方面,這意味著要平穩(wěn)起來,在起點附近移動需要更長的時間并且到達目的地需要更長的時間(加速和減速)。
在Unity中
插值背后的數(shù)學比你想象的要簡單得多。事實上,讓我們仔細看看它在Unity3d冒險中的實際情況。經(jīng)典的Mathf.Lerp。
回顧一下,讓我們自己提醒我們使用的Interpolate函數(shù):
public float Interpolate(float start, float goal, float time)
{
var difference = goal-start;
return start + difference * time;
}
希望現(xiàn)在它更有意義?,F(xiàn)在,讓我們引擎蓋下偷看,看看到底是什么Mathf.Lerp是真正這樣做的:
public static float Lerp(float a, float b, float t)
{
return a + (b - a) * Mathf.Clamp01(t);
}
看起來非常相似,對嗎?
除了添加的將t 限制在0 和1 之間的Clamp之外,它的功能完全相同。
接下來是什么?
現(xiàn)在我們知道了Lerp實際上是什么,以及它做了什么,在第二部分中我們將看看如何使它更有用(以曲線的形式)。