在游戏中,我们经常想实现一些动画效果。比如:物体缓慢转动、沿不规则路线运动、UI淡入淡出、颜色变化、等等。
其实这些效果的背后,都跟一个函数有关系–Lerp
当你了解并掌握这个函数,实现上面的效果对你来说都非常简单。
在本文中,我将分享一下:
- 使用经验
- 使用误区
- 不规则路线的移动
什么是线性插值 ?
两个向量之间的任意值。如图:
向量A,向量B。他们之间的线段AB。在线段AB之间的值,就是线性插值。
对应的 Unity 的 Lerp 函数 Lerp(A, B, 比率t);
比率范围时 0~1 的情况下:
当比率是0时,那插值等于A点。
当比率是1时,插值等于B点。
Unity Lerp 相关函数有哪些?
- Material.Lerp : 材质之间的插值
- Vector2.Lerp : 向量之间的插值
- Vector3.Lerp : 向量之间的插值
- Mathf.Lerp : 浮点数之间的插值
- Color.Lerp : 颜色之间的插值
到此为止,如果你理解什么是线性插值。那你应该知道怎么在 Unity 里使用它了。
但是,如果你就此满足。你可能会在漏掉一些细节,从而导致不理想的效果。
使用经验
移动
我们先简单用 Lerp 函数实现物体的 在 1S 内移动。
代码如下:
public class Lerp : MonoBehaviour
{
// 终点
public Vector3 targetPosition;
// 开始位置
public Vector3 startPosition;
// 持续时间
public float lerpDuration = 1f;
// 记录运行时间
private float _timeElapsed = 0;
private void Start()
{
transform.position = startPosition;
}
void Update()
{
// 记录这一帧移动的位置
Vector3 valueToLerp;
_timeElapsed += Time.deltaTime;
if ((_timeElapsed < lerpDuration))
{
valueToLerp = Vector3.Lerp(startPosition, targetPosition, _timeElapsed / lerpDuration);
transform.position = valueToLerp;
}
else
{
valueToLerp = targetPosition;
}
transform.position = valueToLerp;
}
}
效果:
好的,这么一个移动效果就完成了。
取线段的任意一点
换个角度,我们也可以取得 AB 线段上的任意一点的坐标。
代码如下:
public class GetPoint : MonoBehaviour
{
// 坐标点A
public Vector2 a;
// 坐标点B
public Vector2 b;
// 比值
public float ratio;
private void Update()
{
var position = Vector3.Lerp(a, b, ratio);
transform.position = position;
}
}
效果如下:
其他的线性变化效果其实也是同理,只不过你使用的函数方法可能不一样。
文字淡入淡出

{
elementToFade = gameObject.GetComponent<CanvasRenderer>();
StartCoroutine(LerpFunction(targetValue, 0.8f));
}
IEnumerator LerpFunction(float endValue, float duration)
{
while (true)
{
float time = 0;
float startValue = elementToFade.GetAlpha();
// 淡出
while (time < duration)
{
elementToFade.SetAlpha(Mathf.Lerp(startValue, endValue, time / duration));
time += Time.deltaTime;
yield return null;
}
elementToFade.SetAlpha(endValue);
// 淡入
time = 0;
while (time < duration)
{
elementToFade.SetAlpha(Mathf.Lerp(endValue, startValue, time / duration));
time += Time.deltaTime;
yield return null;
}
elementToFade.SetAlpha(startValue);
}
}
}
渐变
public class LerpMaterialColour : MonoBehaviour
{
private Text text;
public Color targetColor = new Color(0, 1, 0, 1);
void Start()
{
text = gameObject.GetComponent<Text>();
StartCoroutine(LerpFunction(targetColor, 5));
}
IEnumerator LerpFunction(Color endValue, float duration)
{
float time = 0;
Color startValue = text.color;
while (time < duration)
{
text.color = Color.Lerp(startValue, endValue, time / duration);
time += Time.deltaTime;
yield return null;
}
text.color = endValue;
}
}
使用误区
我们平时可能会遇到过,有使用 Lerp 函数实现平滑移动的效果。
效果如下:
代码如下:
public class Lerp_Error1 : MonoBehaviour
{
// 终点
public Vector3 targetPosition;
// 开始位置
public Vector3 startPosition;
private void Start()
{
transform.position = startPosition;
}
void Update()
{
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime);
}
❎ 这使用其实不正确的。因为它实际在改变初始值,通过改变AB之间的距离来得出“插值”。这已经不属于线性插值计算了。
况且,想实现平滑移动的效果,我们其实可以使用 SmoothDamp() 方法。具体使用可以参考这篇文章 TODO。
怎么实现不规则运动?
刚刚我们很容易实现了直线运动,那如果我们能把不规则的路线用直线概括指出来,看起来物体只不过是在进行多段直线运动。
如果觉得还不错,可以点个赞。你的喜欢,是我最大的动力。