c# - 随时间旋转游戏对象

标签 c# unity3d quaternions

我是新来的,我尝试开始使用 Unity 引擎。

谁能给我解释一下,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);

    }

最佳答案

大多数示例,包括来自其官方网站的 Unity 示例,都以错误的方式使用了 Lerp。他们甚至懒得在 API 文档中描述它是如何工作的。他们只是在 Update() 中给它 sizing 功能并收工。

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

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

我会用Mathf.Lerp来解释这个让它更容易理解。 Lerp Mathf.Lerp 的功能完全相同, VectorQuaternion .

记住 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)返回传入数字的mint(1)返回传入的 ma​​x 值和 t(0.5)将返回 minma​​x 值之间的 mid 点。当您传递任何 < 0t 值时,您做错了或 > 1 .你的代码 Update()功能就是这样做的。 Time.time将每秒增加并且将是> 1等一下,所以你遇到了问题。

推荐使用Lerp在另一个函数/协程中而不是更新函数中。

注意:

使用 Lerp在轮换方面有不好的一面。 Lerp不知道如何以最短路径旋转 Object。所以请记住这一点。例如,您有一个 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但需要更多的计算。

关于c# - 随时间旋转游戏对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37586407/

相关文章:

c# - 将图像分割成几 block silverlight Windows Phone

c# - UnityEngine.Events.Unityaction 与 System.Action 之间有什么区别?

qt - 来自向量 x y z 分量的四元数 - 在 Qt 中

c++ - 在 C++ 中对代数结构矩阵使用类的开销

math - 从四元数中提取偏航角

c# - 当我的解决方案中有两个项目时,如何为 SignalR 3.0 指定正确的后端 URL?当前获取 404

c# - 如何为 Lync 2010 和 Skype For Business 编码

c# - XNA - 进程在调试时意外终止

c# - Unity3d SimpleJSON 添加 int 到 JSONClass

android - 基于 Unity 的 Android 游戏屏幕在 Lollipop 下对角线切成两半(但在 Jelly Bean 下不是)