【问题标题】:Rotate an object (model) with rotation of an another object (hand-VR)通过旋转另一个对象(手 VR)来旋转一个对象(模型)
【发布时间】:2021-11-23 18:42:57
【问题描述】:

我正在让一个物体随着手的旋转角度旋转。它运行良好,我能够旋转 3D 模型对象。不幸的是,现在我只希望对象在其 z 轴上旋转。我正在尝试使用 Quaternion.Euler (0, 0, rot.eulerAngles.z); 但不起作用,模型在所有 3 个轴上旋转。我该如何解决?

    public GameObject targetHand;

    [Header ("3D Model")]
    public GameObject powerSwitch;

    [Header ("Hand to 3D Model")]
    public float activationDistance;
    private Quaternion currentRot;
    private Vector3 startPos;
    private bool offsetSet;

    void Update () {

            if ((IsCloseEnough ())) {
                Rotate ();
            } else {
                offsetSet = false;
            }
        
    }
    void Rotate () {

        SetOffsets ();

        Vector3 closestPoint = Vector3.Normalize (targetHand.transform.position - powerSwitch.transform.position);
        var rot = Quaternion.FromToRotation (startPos, closestPoint);
        rot = Quaternion.Euler (0, 0, rot.eulerAngles.z); //Not working when I do this, why?
        powerSwitch.transform.rotation = rot * currentRot;

    }

    void SetOffsets () {
        if (offsetSet)
            return;

        startPos = Vector3.Normalize (targetHand.transform.position - powerSwitch.transform.position);
        currentRot = powerSwitch.transform.rotation;

        offsetSet = true;
    }

    bool IsCloseEnough () {
        if (Mathf.Abs (Vector3.Distance (targetHand.transform.position, powerSwitch.transform.position)) < activationDistance)
            return true;

        return false;
    }

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    您想限制围绕该轴的旋转。

    我创建了一个Extension Method 来像这样钳制每个轴,从而使该功能在项目中的任何位置都可用。

    public static class MyExtensions // Name it what you like I just use this
    {
        public static Quaternion ClampRotationAroundZAxis(this Quaternion q)
        {
            if (!Mathf.Approximately(q.w, 0f)) // Cannot divide by 0f
            {
                // Check values are not 0f before trying to divide them
                q.x = !Mathf.Approximately(q.x, 0f) ? q.x /= q.w : q.x;
                q.y = !Mathf.Approximately(q.y, 0f) ? q.y /= q.w : q.y;
                q.z = !Mathf.Approximately(q.z, 0f) ? q.z /= q.w : q.z;
                q.w = 1f;
            }
            
            // Clamp other rotations
            q.x = 0f;
            q.y = 0f;
    
            return q; // Return self
        }
    }
    
    // Usage
    rotation.ClampRotationAroundZAxis();
    

    编辑:向 OP 显示使用情况

    如果我以正确的方式让它们匹配,您可以像这样匹配它,否则在设置 dir 时交换顺序

    Vector3 dir = (powerSwitch.transform.position - targetHand.transform.position).normalized;
    Quaternion rot = Quaternion.LookRotation(dir, Vector3.up).ClampRotationAroundZAxis();
    powerSwitch.transform.rotation = rot;
    

    【讨论】:

    • 我应该在我的 Rotate() 函数下调用它吗?
    • 您可以像这样设置rot var rot = Quaternion.FromToRotation (startPos, closestPoint).ClampRotationAroundZAxis()
    • @Programmer 我不确定你是否了解扩展类,所以我将方法封装在一个中以更好地展示它。 (它只是一个带有静态类的文件,您可以将静态扩展方法添加到其中)
    • 我添加了你的扩展类,我用你提到的方式称呼它var rot = Quaternion.FromToRotation (startPos, closestPoint).ClampRotationAroundZAxis(),但它仍然无法夹紧它,所有 3 个轴都在波动。
    • 波动可能是因为它太靠近并从一侧翻转到另一侧,至于它不是 Clamping 我不知道你做错了什么,因为我只是仔细检查它并且它有效
    【解决方案2】:

    不敢相信它是多么简单。

    要旋转事物,只需 .z 轴,您应该保留其他轴。示例:

    Transform target;
    
    transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, target.eularAngles.z);
    

    只使用目标 z。

    【讨论】:

    • 我在制作之前尝试过 (0, 0, rot.eulerAngles.z),我正在使用 Quaternion.Euler。