如果角色的头部已经旋转了60°,角色的身体怎么能连续旋转?

时间:2015-06-04 21:14:09

标签: java c# unity3d google-cardboard

经过一些实验,我将一个空的(HeadCam)作为角色的脖子。 此片段允许头部同步旋转到CardboardHead / Camera。

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

enter image description here

当只有头部在-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 applet:https://github.com/3dbug/blender/blob/master/HeadCamRot.java

2 个答案:

答案 0 :(得分: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&amp;传递的旋转的z角度不会超过 maxAngle 。此外,即便如此,如果需要,在上述函数中添加该限制也应该非常简单。

希望它有所帮助。

答案 1 :(得分:1)

最后我找到了解决方案:

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;
    }
}