Unity SteamVR中的瞬移一般都通过设置CameraRig的位置实现,在精度要求不高的情况下,直接设置其位置不会有太大问题。但是,在一些精度要求较高的场合,有时强制设置其位置会导致穿模、摄像机进入其他物体等情况。

原因

CameraRig的中心点是SteamVR房间设置中设置的中心点。玩家戴上头盔后,如果他站立的地方不是之前设置的中心点位置,则其眼睛摄像机及身体碰撞盒等会根据真实位置进行一些偏移。

当我们强制移动CameraRig的位置时,由于玩家相对于CameraRig中心点有一定偏移,因此玩家可能进入其他模型内部导致穿模。

综上所述,原因:虽然CameraRig移动到了你想要的地方,但是其下的玩家身体并没有在CameraRig的中心。

解决方法

解决方法很简单,瞬移的目的是将Camera(Eye)代表的玩家身体移动到目标位置,因此计算一下玩家身体与CameraRig的偏移量,根据偏移量计算CameraRig需要瞬移的正确位置既可。

//摘自开发版VRTK_BasicTeleport脚本
protected virtual Vector3 GetCompensatedPosition(Vector3 givenPosition, Vector3 defaultPosition)
{
    float newX = 0f;
    float newY = 0f;
    float newZ = 0f;

    if (ValidRigObjects())
    {
        newX = (headsetPositionCompensation ? (givenPosition.x - (headset.position.x - playArea.position.x)) : givenPosition.x);
        newY = defaultPosition.y;
        newZ = (headsetPositionCompensation ? (givenPosition.z - (headset.position.z - playArea.position.z)) : givenPosition.z);
    }

    return new Vector3(newX, newY, newZ);
}

VRTK现成的方法

如果嫌自己计算太麻烦的话,不妨考虑一下Github上开发版的VRTK插件。在新版VRTK的基础传送脚本VRTK_BasicTeleport中,已经为用户封装好了可以用代码调用的精确瞬移方法,其精确瞬移方法就是通过上面提到的原理实现的。
脚本名称:VRTK_BasicTeleport(仅限于开发版,见VRTK github仓库)

//传送(包含对偏移的处理)
//参数:target:目的地的物体(标记,在瞬移中没用),destinationPosition:瞬移世界坐标,destinationRotation:旋转,forceDestinationPosition:瞬移目标点是否改变
public virtual void Teleport(Transform target, Vector3 destinationPosition, Quaternion? destinationRotation = null, bool forceDestinationPosition = false)
//强制传送(包含对偏移的处理),忽略碰撞、阻碍、地板等
//参数:destinationPosition: 要移动的世界坐标点,destinationRotation:欲进行的旋转
teleporter.ForceTeleport(Vector3 destinationPosition, Quaternion? destinationRotation = null);

引用资料

1、[头图]【Unity】Unity-Japan UnityChanSD角色

我来吐槽

*

*

3位绅士参与评论

  1. mikusa08-29 21:01 回复

    接下来就该写裁剪图片的啦!

  2. LingC08-29 17:26 回复

    这太酷了

  3. littleplus08-28 13:21 回复

    兔子写的文章好多Unity的,这是工作需求?

    • 野兔08-28 21:57 回复

      没办法,别的又不会,只能写写这个装装样子。