当人物的头部已经旋转了60度,如何使其身体继续旋转?

16

经过一些尝试,我将一个空的(HeadCam)绑定到角色的脖子上。 这段代码允许头部与CardboardHead /相机同步旋转。

void LateUpdate() {
    neckBone.transform.rotation = Camera.transform.rotation *  Quaternion.Euler( 0,0,-90);
    Camera.transform.position = HeadCam.transform.position;
}

在此输入图片描述

当仅头部旋转时,人物的手臂不应该移动,只要在-60°到60°的范围内。然后我想移动整个角色,但手臂仍然可见。以下方法只适用于人物旋转180°以内,之后人物会翻转180°。如何实现恒定旋转?

void LateUpdate() {
    Quaternion camRot = Camera.transform.rotation * Quaternion.Euler( 0,0,-90);                 
    neckBone.transform.rotation = camRot;
    float yrot = camRot.eulerAngles.y;
    float ydelta = 0;
    if ( yrot < 300f && yrot > 180 ) {
        ydelta = yrot - 300f;
    }
    if ( yrot > 60f && yrot < 180 ) {
        ydelta = yrot - 60;
    }
    playerObj.transform.rotation =  Quaternion.Euler(0, ydelta, 0); 
    Camera.transform.position = HeadCam.transform.position;
}

enter image description here

用于测试算法的Java小程序:https://github.com/3dbug/blender/blob/master/HeadCamRot.java


你不能使用更简单的动画来实现这个目的吗? - leAthlon
@leAthlon 这是一个虚拟现实应用程序,旋转必须根据相机的移动实时应用。基本上,当您向下看时,您会看到自己。 - stacker
我不确定虚拟现实的事情 - 或许Unity5预制件中的mouselook脚本可以帮助你。 - leAthlon
啊,我明白了。嗯,其实我一开始并没有明白,但现在我懂了。 - anon
2个回答

3

一种可能的解决方案如下:

// Transform of the full body of the character.
Transform body;
// Transform of the head (child of |body| component).
Transform head;
// Maximum delta angle in degrees.
float maxAngle = 60.0f;

void RotateCharacter(Quaternion target) {
  // Rotate head as much as possible without exceeding the joint angle.
  head.rotation = Quaternion.RotateTowards (body.rotation, target, maxAngle);
  // Complete the remainder of the rotation by body.
  body.rotation = target * Quaternion.Inverse (head.localRotation);
}

请记住,在进行非水平旋转之前,您可能需要限制旋转角度,即我假设给定的旋转的 x 和 z 角度不会超过 maxAngle。此外,即使如此,如果需要,在上述函数中添加该限制也应该非常简单。
希望这有所帮助。

谢谢,应该使用什么作为目标?目前我从Cardboard相机中读取旋转并基于此进行计算。 - stacker
硬纸板相机的方向(Transform.rotation)应该是这种情况下的目标。当然,如果您的角色模型有一些初始方向,即不同于相机的初始方向,则您还应考虑将其匹配为最终旋转。 - anokta
再次感谢,这可能需要更多的时间来做到完美。当我找到解决方案时,我会在这里发布。问题可以归结为Unity在0和360°上旋转的行为,因此计算需要考虑到这一点。在某些情况下,Quaternion.RotateTowards可能非常有帮助。 - stacker

1
最终我找到了解决方案:

Finally I found a solution for this:

private float bodyRot = 0F;
private float FOV = 70f;

void LateUpdate() {
    if ( neckBone != null ) {
        Quaternion camRotQ = CameraFacing.transform.rotation * Quaternion.Euler( 0,0,-90);
        neckBone.transform.rotation = camRotQ;
        float camRot = camRotQ.eulerAngles.y;

        float delta = camRot- bodyRot;
        if ( delta > 180 ) {
            delta -= 360;
        }
        if ( delta < -180 ) {
            delta += 360;
        }
        if ( Math.Abs(delta) > FOV ) {
            if ((delta > FOV || delta < -180) && delta < 180) {
                bodyRot = camRot - FOV;
            }
            delta = camRot- bodyRot;
            if ((delta < FOV || delta > 180 ) ) {
                bodyRot = camRot + FOV;
            }
        }
        playerObj.transform.rotation =  Quaternion.Euler(0, bodyRot, 0); 
        CameraFacing.transform.position = cameraMount.transform.position;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接