----------------------转自Unity Connect
介绍
在我看来,插值是设计中最酷的概念之一。如果您正在制作游戏,用户界面或动画,则无关紧要。没有别的东西可以让你在一小段变化的质量方面获得更大的收益。
当我第一次开始游戏开发时,我对这个想法很陌生,坦率地说,数学让我感到害怕。它似乎很复杂,也是无法接近的,但实际上这个概念有多么简单。一旦理解了基本原理,可能性就是无穷无尽的。
什么是插值?
Interpolation的核心是在两个值之间创建新数据的行为。换句话说,允许您平稳地从一个数字移动到另一个数字。在动画示例中,您可以看到这些值可以是“ 位置” ,“ 可见性” 或“ 颜色”中的任何值。
基本
在我们想到任何想象之前,让我们开始吧。我们来做一些超级基础数学。
如果我给你3号,并说目标是10 ,你怎么到达那里?
你加7,对吗?
让我们将它们标记为开始,差异和目标。
简而言之:
开始+差异=目标
(我知道,我知道......和我在一起)
这是有趣的地方。让我再添加一个号码,我们称之为时间。这个新数字只会是0 到1 之间的某个数字。让我们看看当我们改变公式时会发生什么。
开始+(差异*时间)=?
如果我们为时间传递0 ,我们得到.... 开始,但如果我们传入1,我们得到目标。
还是很简单吧?如果我们通过在....会发生什么0.5 ?我们在Start 和Goal 之间获得了一半。
那......基本上就是它!你所拥有的是线性插值的整个概念。就实际代码而言:
让我们看看它的实际效果:
线性插值
</figure>
这是整个核心概念。
其他一切都建立在这个想法之上。要记住的重要一点是,未来唯一改变的是时间。(它只会在0 和1 之间)。
非线性插值
我们上面创建的是动作。在物理学术语中,你应该看到与运动方程的相似性。在一天结束时,这就是我们正在做的事情,随着时间的推移,我们正在从一个位置移动到另一个位置。
然而,上面的那种动作,坦率地说...... 无聊。它是线性的。它在同一时间传播完全相同的距离。它需要相同的时间才能达到中途点,从中途到结束。
这不是现实生活中的动作。
在现实生活中,移动物品有加速度。汽车不会从无动作变为设定速度并立即停止。它坡道慢慢加快速度,临近年底它会减慢。
我们如何得到我们的等式呢?用最简单的术语来说,我们改变时间。我们截取值Time 并在将它应用于对象之前对其进行更改。我们来看一些代码:
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。
如果我们将两者结合起来:
[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 之间取一些值来表示已经过了多少时间并且捏造数字,因此移动者处于转换的不同百分比而不是实时。
在动画方面,这意味着要平稳起来,在起点附近移动需要更长的时间并且到达目的地需要更长的时间(加速和减速)。
在Unity中
插值背后的数学比你想象的要简单得多。事实上,让我们仔细看看它在Unity3d冒险中的实际情况。经典的Mathf.Lerp。
回顾一下,让我们自己提醒我们使用的Interpolate函数:
public float Interpolate(float start, float goal, float time)
{
var difference = goal-start;
return start + difference * time;
}
希望现在它更有意义。现在,让我们引擎盖下偷看,看看到底是什么Mathf.Lerp是真正这样做的:
public static float Lerp(float a, float b, float t)
{
return a + (b - a) * Mathf.Clamp01(t);
}
看起来非常相似,对吗?
除了添加的将t 限制在0 和1 之间的Clamp之外,它的功能完全相同。
接下来是什么?
现在我们知道了Lerp实际上是什么,以及它做了什么,在第二部分中我们将看看如何使它更有用(以曲线的形式)。