我是新手,我尝试开始使用Unity Engine。
有人可以解释一下,Quaternion.Slerp是如何运作的?因为我想以不同的角度90,180和270旋转一些物体。我可以在下面看到我的代码。不幸的是,当我添加180度时,对象会做出疯狂的事情,而不是将旋转放到(0,180,180)这个游戏对象。我想得到(180,0,0)
{"platillos":{"columns":["id_platillo","codigo"],"records":[["1","HAMB01"]]}}
答案 0 :(得分:12)
其中包含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 值,{ {1}}将在 min 和 max 值之间返回 mid 点。当您传递t(0.5)
或< 0
的任何 t 值时,您做错了。你> 1
函数中的代码就是这样做的。 Update()
每秒都会增加,并且会在一秒钟内增加Time.time
,所以你有问题。
建议在另一个函数/ Coroutine中使用> 1
而不是更新函数。
注意:
使用Lerp
在轮换时有不好的一面。 Lerp
不知道如何使用最短路径旋转Object。所以记住这一点。例如,您有一个Lerp
位置的对象。假设您想要将旋转从0,0,90
0,0,120
移动到有时可以向左旋转而不是向右旋转以达到新位置,这意味着需要更长时间才能达到该距离。
让我们说我们想要从当前轮换中进行轮换Lerp
。下面的代码会在3秒内将轮换更改为(0,0,90)
。
超时旋转:
0,0,90
时间上的增量角度旋转:
要在z轴上将对象旋转到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;
}
我的所有示例都基于设备的帧速率。您可以将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
来实时使用,但需要进行更多计算。
答案 1 :(得分:1)
在此之前,你不能在这样的欧拉角上添加180,这主要是造成问题的原因。你最好直接使用四元数,或者自己进行变换。
您可以将四元数视为空间方向。与已经说过的相反,如果可以的话,我建议学习如何使用它们。但是,我建议不要使用欧拉角......因为它们会采用不同的写作惯例,有时会失败。如果你想了解详细信息,可以查看“万向节锁”。
简单地说slerp或lerp(分别代表球面线性插值或线性插值)是一种插值方式(从一个方向转到另一个方向,通过在协程或其他任何地方将t从0增加到1) A和B.两者之间的区别在于,slerp为您提供了从A到B的最短路径。
最后,当t = 1时,lerp(A,B,t)和slerp(A,B,t)会给你B.
在您的情况下,如果您想立即将空间中的对象旋转到特定方向,我建议您使用Quaternion.AngleAxis,它是以数学方式描述四元数的最前沿方式。
如果你想添加一个旋转,比如说实际方向是90°(两者之间没有动画),你可以这样做:
transform.rotation * = Quaternion.AngleAxis(axis_of_rotation,angle) 或者使用transform.rotate(取决于参数,它可以是右乘,或左:本地或世界变换)。
程序员的回答是详细说明如何为变换设置动画。但我确实建议你自己研究四元数,因为它会让你全面了解空间变换。