【问题标题】:How to constraint object rotation to certain degree?如何在一定程度上限制物体旋转?
【发布时间】:2016-12-21 14:30:59
【问题描述】:

我有一个由物理白日梦控制器控制的方向盘(它的工作原理类似于 wii 控制器)。我使用这段代码来做到这一点:

void Update() {
    transform.localRotation = GvrController.Orientation;
    transform.localRotation = new Quaternion(0.0f, 0.0f, -transform.localRotation.y, transform.localRotation.w);
}

我需要弄乱轴,因为控制器的默认位置不适合方向盘。

但在 3 轴上,向左和向右的最大旋转角度为 180 度。在这个范围内一切都很好,但如果我再旋转一点,这个值就会变成负数,一切都搞砸了。我该怎么做才能让玩家只在这个范围内旋转(3 轴旋转的 z 轴上的 0 - 180)?

编辑:主要问题是经过 0 或 180 后的旋转值变为负值,两者相同,但顺序不同。越过 0 后,它形成 -1 到 -180,而对于 180,它形成 -180 到 -1。

【问题讨论】:

    标签: c# unity3d quaternions


    【解决方案1】:

    首先,我们需要一个可以实际钳位的值。我们将从eulerAngles.z 字段中获得它(因为典型的屏幕轮子围绕 z 旋转 - 您可能需要根据控制器将其更改为其他字段):

    void Update() {
    
        // Get the angle:
        float angle = GvrController.Orientation.eulerAngles.z;
    
        // The magic - clamp it:
        if(angle < -180f){
            angle = -180f;
        }
        else if(angle > 180f){
            angle = 180f;
        }
    
        // Apply it as a new rotation:
        transform.localRotation = Quaternion.Euler(0f,0f,angle);
    }
    

    【讨论】:

    • Quaternion.AngleAxis 将 float 和 Vector3 作为参数,我应该使用不同的函数吗?
    • @faken 已编辑:改用 Quaternion.Euler
    • 当我使用它时,它更加混乱,即使在“范围”内也能正常工作。我认为这是因为将 Vector3 转换为四元数。
    • @faken 您可能需要更改轴(因为这取决于控制器)。 IE。也许改用eulerAngles.y。在您的问题中,您直接使用四元数的“y”组件,简而言之,这会给您带来意想不到的结果。
    • @faken 好的,我明白你现在在说什么了——如果使用得当,四元数非常棒。控制器不知道您将其倒置——它只知道它的绝对方向。那么您真正要寻找的是如何避免当有人将控制器倒置然后“继续前进”时引起的非常突然的“震动”?
    【解决方案2】:

    试试这个:

    if (transform.eulerAngles.z > 180)
         transform.eulerAngles = new Vector3(transform.eulerAngles.y, transform.eulerAngles.y, 180);
    else if (transform.eulerAngles.z < 0)
         transform.eulerAngles = new Vector3(transform.eulerAngles.y, transform.eulerAngles.y, 0);
    

    【讨论】:

    • 由于我在 EDIT 中写的内容,这一切都搞砸了:/
    • 我有一个关于代码的小问题。您是否使用 euerAngles.y 为 z 轴创建新的旋转,因为 Z 旋转围绕该轴旋转?或者可以解释一下为什么你使用 Y 值,而不是 X 和 Y,或者只是 Z 值?
    • 是的,这段代码不能正常工作。它弄乱了旋转
    【解决方案3】:

    如果有人想知道我找到了一个解决方案,基于卢克回答的脚本。我意识到变成负数的值很好,唯一的问题是它们是负数。所以这是工作脚本:

    transform.localRotation = GvrController.Orientation;
    
    float angle = -transform.localRotation.y;
    
    if (angle < 0.0f) {
        angle = Mathf.Abs(angle);
    }
    
    transform.localRotation = new Quaternion(0.0f, 0.0f, angle, transform.localRotation.w);
    

    【讨论】:

    • FWIW 您仍在使用四元数的原始组件,这在某些情况下会产生意想不到的结果。四元数代表一个角度和一些任意轴(例如,有两种解决方案会给出相同的可见旋转,但 y 分量完全不同 - 所以它在您的使用中会出现损坏)。
    • 我不知道,可能你是对的,但它效果很好,所以看来我只是幸运。
    【解决方案4】:

    试试这个:

    If (transform.rotation > 180)
         transforn.rotation = 180;
    

    【讨论】:

    • 这有大约 3 个问题。首先,我们使用的是localRotation,而不是rotation,其次,您正在检查旋转是否为 180 度。 什么?,你必须检查一个轴。第三,它会变成负数,所以即使它写得正确,这个检查也无法解决问题,因为它应该是if(transform.localRotation.z &lt; 0)
    • 请使用edit链接解释这段代码是如何工作的,不要只给出代码,因为解释更有可能帮助未来的读者。另请参阅How to Answer
    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多