为双边移动统一镜像 Oculus Rift 控制器位置

Mirroring Oculus Rift controller positions in unity for bilateral movement

目前我正在尝试编写一个脚本,为只有一个功能手臂的用户将一个控制器的运动镜像到另一个控制器上。我如何将一个控制器的位置镜像到另一个控制器,使手臂在双边运动中?

镜像 y 轴和 z 轴很容易,因为它们一起移动并且旋转很容易镜像。我无法镜像 x 轴运动。我想要这样,如果一只手移出,另一只手也移出,并且它们一起移入。有什么想法我可以做到这一点吗?我附上了我目前的剧本。 我还在 OVRCemeraRig 脚本中使用简单的布尔逻辑禁用了非镜像控制器的位置跟踪,以防止运动中的卡顿 需要使用 OVRCemeraRig,因为使用了最终 IK

我试过在工作臂的 x 位置上取不同,然后将该值添加到 none 工作臂。那没有用。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class VRMirror : MonoBehaviour
{
    public bool mirrorLeft;
    public bool mirrorRight;
    public GameObject leftHand; //left hand anchor in OVRCameraRig
    public GameObject rightHand; //right hand anchor from OVRCameraRig
    void Start()
    {

    }
    void FixedUpdate()
    {
        Transform left = leftHand.GetComponent<Transform>();
        Transform right = rightHand.GetComponent<Transform>();
        if (mirrorLeft)
        {
            Vector3 leftPos = left.position;
            Quaternion leftRot = left.rotation;
            leftRot.y = -leftRot.y;
            right.position = leftPos;
            right.rotation = leftRot;
        }
        else if (mirrorRight)
        {
            Vector3 rightPos = right.position;
            Quaternion rightRot = right.rotation;

            rightRot.y = -rightRot.y;
            left.position = rightPos;
            left.rotation = rightRot;

        }
    }
}

为了稳健起见,我们假设您的玩家 body 的旋转不一定总是正确指向 (1,0,0) 世界方向。相反,我们可以获得对玩家变换 playerTransform 的引用(如果必须,请务必使用检查器或在 Start 中分配它)并使用它进行计算。

要计算相对向量的双边对称位置,可以计算relativeVec - 2f * playerTransform.right * Vector3.Dot(relativeVec, playerTransform.right);。评论中解释了为什么有效。

对于位置,我们可以将源手的绝对位置转换为相对于玩家位置的位置,然后找到目标手的相对位置,然后将其转换回绝对位置。

对于旋转,确定源手的向上和向前并反映它们以确定目标手的向上和向前。使用 Quaternion.SetLookRotation 将矢量转换为目标手的旋转。

我们可以对相对位置和方向向量使用相同的代码,所以一旦你掌握了数学知识,实际上不需要太多代码。而且,由于 Transform 是一个 class,我们可以创建一个执行反射过程的方法,然后将其传递给它,转换我们想要成为源和目标的方法:

public class VRMirror : MonoBehaviour
{
    public bool mirrorLeft;
    public bool mirrorRight;
    public GameObject leftHand; //left hand anchor in OVRCameraRig
    public GameObject rightHand; //right hand anchor from OVRCameraRig

    public Transform playerTransform;

    void Start()
    {

    }
    void FixedUpdate()
    {

        Transform left = leftHand.GetComponent<Transform>();
        Transform right = rightHand.GetComponent<Transform>();
        if (mirrorLeft)
        {
            MirrorFromTo(left, right);
        }
        else if (mirrorRight)
        {
            MirrorFromTo(right, left);
        }
    }

    void MirrorFromTo(Transform sourceTransform, Transform destTransform)
    {
        // Determine dest position
        Vector3 playerToSourceHand = sourceTransform.position - playerTransform.position;
        Vector3 playerToDestHand = ReflectRelativeVector(playerToSourceHand);
        destTransform.position = playerTransform.position + playerToDestHand ;

        // Determine dest rotation
        Vector3 forwardVec = ReflectRelativeVector(sourceTransform.forward);
        Vector3 upVec = ReflectRelativeVector(sourceTransform.up);
        destTransform.rotation = Quaternion.LookRotation(forwardVec,upVec);
    }

    Vector3 ReflectRelativeVector(Vector3 relativeVec) 
    {
       // relativeVec
       //     Take the relative vector....
       // + Vector3.Dot(relativeVec, playerTransform.right)
       //     and for how far along the player's right direction it is 
       //     away from the player (may be negative),
       // * playerTransform.right
       //     move it that distance along the player's right...
       // * -2f
       //    negative two times (i.e., along the left direction 2x)

       return relativeVec 
           + Vector3.Dot(relativeVec, playerTransform.right)
               * playerTransform.right 
               * -2f;
    }
}

我对@Ruzihm 的内容做了一些改动。十分感谢你的帮助。在我下面采样的代码中,一切都完美无缺,但我建议@Ruzihm 回答,因为他如何处理轮换。如果播放器模型是静止的并且您没有完全转动 body,则此代码有效。如果需要转动,请在 ReflectRelativeVector 函数中使用 playerTransform.right 而不是 Vector3.right,但使用 playerTransform.right 将在头部移动时移动手臂。

public class VRMirror : MonoBehaviour
{
    public bool mirrorLeft;
    public bool mirrorRight;
    public GameObject leftHand; //left hand anchor in OVRCameraRig
    public GameObject rightHand; //right hand anchor from OVRCameraRig

    public Transform playerTransform;  

    void Start()
    {

    }
    void FixedUpdate()
    {

        Transform left = leftHand.GetComponent<Transform>();
        Transform right = rightHand.GetComponent<Transform>();
        if (mirrorLeft)
        {
             MirrorFromTo(left, right);
        }
        else if (mirrorRight)
        {
            MirrorFromTo(right, left);

        }
    }

    void MirrorFromTo(Transform sourceTransform, Transform destTransform)
    {
        // Determine dest position
        Vector3 playerToSourceHand = sourceTransform.position - playerTransform.position;
        Vector3 playerToDestHand = ReflectRelativeVector(playerToSourceHand);
        destTransform.position = playerTransform.position + playerToDestHand;

        // Determine dest rotation
        Quaternion destRot = sourceTransform.rotation;

        destRot.y = -destRot.y;
        destRot.z = -destRot.z;
        destTransform.rotation = destRot;

    }

    Vector3 ReflectRelativeVector(Vector3 relativeVec)
    {
        // relativeVec
        //     Take the relative vector....
        // + Vector3.Dot(relativeVec, playerTransform.right)
        //     and for how far along the player's right direction it is 
        //     away from the player (may be negative),
        // * playerTransform.right
        //     move it that distance along the player's right...
        // * -2f
        //    negative two times (i.e., along the left direction 2x)

        return relativeVec
        + Vector3.Dot(relativeVec, Vector3.right)
            * Vector3.right
            * -2f;
    }
}

编辑器截图如下: