随着时间的推移旋转GameObject

时间:2016-06-02 08:24:11

标签: c# unity3d quaternions

我是新手,我尝试开始使用Unity Engine。

有人可以解释一下,Quaternion.Slerp是如何运作的?因为我想以不同的角度90,180和270旋转一些物体。我可以在下面看到我的代码。不幸的是,当我添加180度时,对象会做出疯狂的事情,而不是将旋转放到(0,180,180)这个游戏对象。我想得到(180,0,0)

{"platillos":{"columns":["id_platillo","codigo"],"records":[["1","HAMB01"]]}}

2 个答案:

答案 0 :(得分:12)

其中包含Unity示例的大多数示例都是以错误的方式使用Lerp。他们甚至懒得描述它在API文档中的工作原理。他们只是将它淀粉在Update()函数中并称之为一天。

Mathf.LerpVector3.LerpQuaternion.Slerp通过传入 t 值(最后一个参数)从一个位置/旋转更改为另一个位置/旋转。 t 值也称为时间。

t 值的最小值 0f ,最大值 1f

我将使用Mathf.Lerp对此进行解释,以便更容易理解。 LerpMathf.LerpVector 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(取决于参数,它可以是右乘,或左:本地或世界变换)。

程序员的回答是详细说明如何为变换设置动画。但我确实建议你自己研究四元数,因为它会让你全面了解空间变换。