角色的body头已经转了60°了,怎么还能继续旋转呢?
How can character's body be continuously rotated when its head is already turned by 60°`?
经过一些试验后,我将一个空的 (HeadCam) 放在角色的脖子上。
此代码段允许头部与 CardboardHead/Camera 同步旋转。
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;
}
用于独立测试算法的 java 小程序:https://github.com/3dbug/blender/blob/master/HeadCamRot.java
一个可能的解决方案是:
// 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 角度不会超过 最大角度。此外,即便如此,如果需要的话,也可以在上面的函数中添加该限制。
希望对您有所帮助。
最后我找到了解决办法:
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;
}
}
经过一些试验后,我将一个空的 (HeadCam) 放在角色的脖子上。 此代码段允许头部与 CardboardHead/Camera 同步旋转。
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;
}
用于独立测试算法的 java 小程序:https://github.com/3dbug/blender/blob/master/HeadCamRot.java
一个可能的解决方案是:
// 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 角度不会超过 最大角度。此外,即便如此,如果需要的话,也可以在上面的函数中添加该限制。
希望对您有所帮助。
最后我找到了解决办法:
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;
}
}