一尘不染

随着时间旋转GameObject

c#

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

有人可以解释一下,Quaternion.Slerp如何工作?因为我想以90、180和270度的角度旋转某个对象。我的代码如下所示。不幸的是,当我增加180度时,对象会做出疯狂的事情,而不是将此游戏对象的旋转度设为(0,180,180)。我想得到(180,0,0)

    public float speed = 0.1F;
    private float rotation_x;
    void Update()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            rotation_x = transform.rotation.eulerAngles.x;
            rotation_x += 180;
        }
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(rotation_x, transform.eulerAngles.y, transform.eulerAngles.z), Time.time * speed);

    }

阅读 252

收藏
2020-05-19

共1个答案

一尘不染

那里的大多数示例,包括其官方网站上的Unity示例,都以错误的方式使用了Lerp。他们甚至不费心地在API文档中描述它的工作方式。他们只是将其添加到Update()函数中,并称之为一天。

Mathf.LerpVector3.Lerp以及Quaternion.Slerp通过从一个位置/旋转变换到另一种与工作
值(最后一个参数)被传递in.That 值也被知道为时间。

所述的最小 值是 0F 和max为 1F

我将对此进行解释,Mathf.Lerp以使其更易于理解。该Lerp功能是所有的,两者相同Mathf.LerpVectorQuaternion

请记住,这Lerp需要两个值并在它们之间返回值。如果我们的值是 110 ,则对它们执行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)返回 分钟 传入的数量,t(1)返回的 最大 传入值,并t(0.5)返回 中旬 的点之间的
最小最大 的价值。当传递任何 t< 0或时,您做错了> 1Update()函数中的代码就是这样做的。Time.time会每秒增加,并且会> 1在一秒内增加,因此您会遇到问题。

建议Lerp在其他功能/协程中使用而不是更新功能。

注意事项

Lerp在旋转方面,使用有不好的一面。Lerp不知道如何以最短的路径旋转对象。所以请记住这一点。例如,您有一个带有0,0,90位置的对象。假设您要将旋转方向从移到,0,0,120
Lerp有时可以向左旋转而不是向右旋转才能到达新位置,这意味着到达该位置需要更长的时间。

假设我们(0,0,90)要从当前旋转角度开始旋转。以下代码将0,0,90在3秒内将旋转更改为。

随时间旋转

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但需要更多的计算。

2020-05-19