大多数示例,包括其官方网站上的 Unity 示例,都以错误的方式使用 Lerp。他们甚至懒得在 API 文档中描述它是如何工作的。他们只是将其添加到 Update() 函数中,然后收工。
Mathf.Lerp、Vector3.Lerp 和 Quaternion.Slerp 通过传入 t 值(最后一个参数)从一个位置/旋转更改为另一个位置/旋转来工作。那 t 值也称为时间。
t值的最小值为0f,最大值为1f。
我将用Mathf.Lerp 解释这一点,以便更容易理解。 Lerp 函数对于 Mathf.Lerp、Vector 和 Quaternion 都是相同的。
请记住,Lerp 接受两个值并返回它们之间的值。如果我们有 1 和 10 的值并且我们对它们进行 Lerp:
float x = Mathf.Lerp(1f, 10f, 0f); will return 1.
float x = Mathf.Lerp(1f, 10f, 0.5f); will return 5.5
float x = Mathf.Lerp(1f, 10f, 1f); will return 10
如您所见,t(0) 返回传入数字的 min,t(1) 返回传入的 max 值,t(0.5) 将返回min 和 max 值之间的 mid 点。当您传递 < 0 或 > 1 的任何 t 值时,您做错了。 Update() 函数中的代码就是这样做的。 Time.time 每秒都会增加,并且会在一秒钟内变为 > 1,所以你有问题。
建议在另一个函数/协程中使用Lerp,而不是Updated函数。
注意:
使用Lerp 在旋转方面有不好的一面。 Lerp 不知道如何用最短路径旋转对象。所以请记住这一点。例如,您有一个具有0,0,90 位置的对象。假设您想将旋转从该位置移动到 0,0,120 Lerp 有时会向左而不是向右旋转以到达新位置,这意味着到达该距离需要更长的时间。
假设我们想从当前的旋转中进行(0,0,90) 的旋转。下面的代码将在 3 秒内将旋转更改为 0,0,90。
随时间轮换:
void Start()
{
Quaternion rotation2 = Quaternion.Euler(new Vector3(0, 0, 90));
StartCoroutine(rotateObject(objectToRotate, rotation2, 3f));
}
bool rotating = false;
public GameObject objectToRotate;
IEnumerator rotateObject(GameObject gameObjectToMove, Quaternion newRot, float duration)
{
if (rotating)
{
yield break;
}
rotating = true;
Quaternion currentRot = gameObjectToMove.transform.rotation;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
gameObjectToMove.transform.rotation = Quaternion.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
rotating = false;
}
随时间的增量角旋转:
并且只是将对象在 z 轴上旋转到 90,下面的代码就是一个很好的例子。请理解将对象移动到新的旋转点和仅仅旋转它是有区别的。
void Start()
{
StartCoroutine(rotateObject(objectToRotate, new Vector3(0, 0, 90), 3f));
}
bool rotating = false;
public GameObject objectToRotate;
IEnumerator rotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration)
{
if (rotating)
{
yield break;
}
rotating = true;
Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles;
Vector3 currentRot = gameObjectToMove.transform.eulerAngles;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
rotating = false;
}
我的所有示例均基于设备的帧速率。您可以通过将Time.deltaTime 替换为Time.delta 来使用实时,但需要进行更多计算。