不太理解四元数旋转(欧拉角)

Can't quite understand quaternion rotation (euler angles)

我目前正在开发一款益智游戏,我正在努力的部分 - 一个可以旋转的齿轮。这是一个 3d 模型,单击左侧后,它应逆时针旋转 40 度,右侧相反。无论如何旋转发生在 y 轴上,它一切正常,直到 y 旋转进入负角 (-40) 在这种情况下而不是向左旋转,而是旋转回 0。这是 Move 方法中的代码更新:

StartCoroutine(RotateGearA(Vector3.right * 40, 1));

协程在这里:

IEnumerator RotateGearA(Vector3 byAngles, float inTime) {
    isMoving = true;
    var fromAngle = cogA.transform.rotation;
    var toAngle = Quaternion.Euler(cogA.transform.eulerAngles + byAngles);
    for(var t = 0f; t < 1; t += Time.deltaTime/inTime) {
        cogA.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t);
        yield return null;
    }
}

我不确定是否应该在 Move() 方法中实现 if-else 语句来处理边缘情况,或者是否有其他方法?

发生这种情况是因为您不只是将动态值添加到欧拉角。

When using the .eulerAngles property to set a rotation, it is important to understand that although you are providing X, Y, and Z rotation values to describe your rotation, those values are not stored in the rotation. Instead, the X, Y & Z values are converted to the Quaternion's internal format.

When you read the .eulerAngles property, Unity converts the Quaternion's internal representation of the rotation to Euler angles. Because, there is more than one way to represent any given rotation using Euler angles, the values you read back out may be quite different from the values you assigned. This can cause confusion if you are trying to gradually increment the values to produce animation.

To avoid these kinds of problems, the recommended way to work with rotations is to avoid relying on consistent results when reading .eulerAngles particularly when attempting to gradually increment a rotation to produce animation. For better ways to achieve this, see the Quaternion * operator.

所以一般来说,为了向现有旋转添加旋转,您应该使用 Quaternion operator *

IEnumerator RotateGearA(Vector3 byAngles, float inTime) 
{
    isMoving = true;

    var fromAngle = cogA.transform.rotation;
    var toAngle = fromAngle * Quaternion.Euler(byAngles);
    for(var t = 0f; t < 1; t += Time.deltaTime / inTime) 
    {
        cogA.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t);
        yield return null;
    }

    // Just to be sure to end with a clean rotation
    cogA.transform.rotation = toAngle;

    // You probably wanted to reset this flag when done ;)
    isMoving = false;
}