对象Unity的旋转以错误的值旋转

时间:2011-12-10 18:03:31

标签: c# rotation unity3d

我的问题是我希望能够将气缸旋转9次。 360/9是40所以我应该做的就是旋转40度9次。然而,这不起作用,因为当我第一次旋转圆柱体而不是旋转40度旋转39.99度时。这也发生在其他轮换中。

我正在这样做。

if(Input.GetKeyUp("i"))
      transform.GetChild(m_Section).Rotate(0,40.0f,0);

我有统一版本3.4它不是专业版,我用C#编码。

任何帮助表示感谢,因为我刚开始尝试学习团结。

2 个答案:

答案 0 :(得分:1)

Unity3D将旋转存储在一个名为quaternion的非常抽象的数学表示中。从Euler角度到Euler角度的转换(你在Unity编辑器中看到的)涉及一系列三角函数,因此容易出现舍入误差,特别是对于简单的浮点型。

为了解决这个问题,我建议在开始旋转之前存储初始的Quaternion对象,并在过程结束时设置它。一些伪代码:

public class RotationController : MonoBehaviour {
    Quaternion rotationAtStart;
    int numOfRotations = 0;

    void rotate () {
        numOfRotations++;
        if (numOfRotations == 1) {
            rotationAtStart = transform.rotation;
        } else if (numOfRotations < 9) {
            transform.Rotate (new Vector3 (0,40.0f,0));
        } else if (numOfRotations == 9) {
            transform.rotation = rotationAtStart;
        }
    }
    void Update () {
        if (numOfRotations < 9) {
            rotate ();
        }
    }
 }   

360°的特殊情况使这种方法稳定。小于360°时,您必须承受小的舍入误差。对于这种情况,我建议计算目标四元数Quaternion.RotateTowards并在最后一步中将其设置为类似于360的情况。

另一个有用的东西是Animations。您可以将动画定义为平滑或不连续的步骤,如果按下“i”,则只需调用GameObject.animation.Play("MyRotation")。在动画终止时,最后使用AnimationEvent获取通知。

最后,Mathf包含一个函数Approximately来处理浮点不精确的问题。

答案 1 :(得分:0)

看看 Kungfooman in this post的答案,他描述了旋转超过90度或90度以及270度的问题。他提供了一个扩展,它将始终为您要设置的值计算Quaternion的正确吊坠。看看这里:

using UnityEngine;
using System.Collections;

public class ExtensionVector3 : MonoBehaviour {

    public static float CalculateEulerSafeX(float x){
        if( x > -90 && x <= 90 ){
            return x;
        }

        if( x > 0 ){
            x -= 180;
        } else {
            x += 180;
        }
        return x;
    }

    public static Vector3 EulerSafeX(Vector3 eulerAngles){
        eulerAngles.x = CalculateEulerSafeX(eulerAngles.x);
        return eulerAngles;
    }
}

我这样使用它:

Quaternion newQuat = m_directionalLight.transform.rotation;
Vector3 nL = new Vector3(ExtensionVector3.CalculateEulerSafeX(xNewValueLight), 
                         0, 
                         0);
newQuat.eulerAngles = nL;

m_directionalLight.transform.rotation = 
     Quaternion.Lerp(m_directionalLight.transform.rotation, 
                     newQuat, 
                     Time.deltaTime);