【问题标题】:Rotation of Object Unity rotating at wrong value对象 Unity 的旋转以错误的值旋转
【发布时间】:2011-12-10 18:03:30
【问题描述】:

我的问题是我希望能够将圆柱体旋转 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# 编码。

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

【问题讨论】:

    标签: c# rotation unity3d


    【解决方案1】:

    Unity3D 以一种非常抽象的数学表示形式存储旋转,称为quaternion。从和到欧拉角的转换(您在 Unity 编辑器中看到的)涉及级联三角函数,因此容易出现舍入错误,尤其是对于简单的浮点类型。

    为了在您的情况下解决此问题,我建议在开始旋转之前存储初始四元数对象并在过程结束时设置它。一些伪代码:

    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 处理浮点不精确的问题。

    【讨论】:

    • 如果我使用你建议的动画会改变对象的局部轴还是只会旋转对象?
    • 您为游戏对象变换的成员设置动画。 transform.rotation 是欧拉角
    • 感谢您的帮助。不过,这更像是一种解决问题的方法,而不是解决方法。我不能说 if(transform.eulerAngles.y == 40.0f) 因为即使旋转方向给出了更准确的结果,仍然存在错误。我还没有尝试过动画建议,但我现在就试一试。
    【解决方案2】:

    看看Kungfoomanin 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      • 1970-01-01
      • 2015-08-20
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多