我正在尝试将播放器绕X,Y和Z轴旋转。 Y轴不应从最后一个角度移动。例如,如果我向左旋转45度,则播放器不应旋转回0。播放器的X和Z轴最多旋转30度,然后在不再使用Input时,请稳定为0。
通过反复试验,我终于使我的Y角不Slerp回到0。但是,X和Z仍然认为Y是0度。播放器旋转了(假定向左旋转45度),但是沿X和Z的移动就好像Y是0度。
我一直在阅读文章和主题,并观看多个领域的视频,包括但不限于StackOverflow,Unity论坛,Unity API和YouTube视频。
Video of Current Game-注意引擎排气-X和Z永远不会更改为“相机”视图/播放器Y方向的新法线。
void Update()
{
if(!controller.isGrounded)
{
//Three degree's
moveDirection = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Thrust"), Input.GetAxis("Vertical"));
moveDirection *= speed;
//rotate around Y-Axis
transform.Rotate(0, Input.GetAxis("Yaw") * rotationSpeed, 0);
float currentY = transform.eulerAngles.y; //save Y for later
//rotation around X and Z
float tiltAroundX = Input.GetAxis("Vertical") * tiltAngle;
float tiltAroundZ = -1 * (Input.GetAxis("Horizontal") * tiltAngle);
Quaternion targetRotation = Quaternion.Euler(tiltAroundX, currentY, tiltAroundZ);
Vector3 finalRotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth).eulerAngles;
finalRotation.y = currentY; //reintroduce Y
transform.rotation = Quaternion.Euler(finalRotation);
controller.Move(moveDirection * Time.deltaTime);
}
答案 0 :(得分:3)
经过进一步的研究使我走上了不同的道路,我发现有两个问题。这两个问题都围绕着这样一个事实,即旋转后Z轴从未归一化为新的Y轴度。 @Ruzihm,解决了旋转问题。我解决了当时可见的运动问题。旋转正常后,即可轻松看到它。
本质上,必须在Y轴旋转(transform.forward
)发生任何变化后重新计算Z轴(Vector3.up
)。一旦有了新的法线(transform.forward
),就需要将运动矢量展平到飞机上,以防止玩家潜入世界表面。谢谢@Ruzihm的所有帮助。
这是新代码:
//Three degree's
moveDirection = new Vector3(Input.GetAxis("Horizontal"),
Input.GetAxis("Thrust"),
Input.GetAxis("Vertical"));
//Normalize the movement direction and flatten the Plane
moveDirection = transform.TransformDirection(moveDirection);
moveDirection = Vector3.ProjectOnPlane(moveDirection, Vector3.up);
moveDirection *= speed;
// collect inputs
float yaw = Input.GetAxis("Yaw") * rotationSpeed;
float pitch = Input.GetAxis("Vertical") * tiltAngle;
float roll = -1 * (Input.GetAxis("Horizontal") * tiltAngle);
// Get current forward direction projected to plane normal to up (horizontal plane)
Vector3 forwardCurrent = transform.forward
- Vector3.Dot(transform.forward, Vector3.up) * Vector3.up;
// Debug to view forwardCurrent
Debug.DrawRay(transform.position, forwardCurrent * 2, Color.white);
// create rotation based on forward
Quaternion targetRotation = Quaternion.LookRotation(forwardCurrent);
// rotate based on yaw, then pitch, then roll.
// This order prevents changes to the projected forward direction
targetRotation = targetRotation * Quaternion.AngleAxis(yaw, Vector3.up);
// Debug to see forward after applying yaw
Debug.DrawRay(transform.position, targetRotation * Vector3.forward, Color.red);
targetRotation = targetRotation * Quaternion.AngleAxis(pitch, Vector3.right);
targetRotation = targetRotation * Quaternion.AngleAxis(roll, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth);
controller.Move(moveDirection * Time.deltaTime);
答案 1 :(得分:2)
在使用欧拉角时,关于旋转顺序的假设似乎有些不正确。施加滚动,然后俯仰,最后偏转。这意味着保持相同的偏航然后将横摇和俯仰设置为零(甚至只是改变横摇)都可以完全改变您所面临的展平方向。
通过偏航旋转可能会有所帮助,使向前的方向变平(也就是将其投影到一个完全水平的平面上),然后基于该旋转(使用Quaternion.LookRotation
),然后可以手动旋转每个轴。
if(!controller.isGrounded)
{
//Three degree's
moveDirection = new Vector3(Input.GetAxis("Horizontal"),
Input.GetAxis("Thrust"),
Input.GetAxis("Vertical"));
moveDirection *= speed;
// collect inputs
float yaw = Input.GetAxis("Yaw") * rotationSpeed;
float pitch = Input.GetAxis("Vertical") * tiltAngle;
float roll = -1 * (Input.GetAxis("Horizontal") * tiltAngle);
// Get current forward direction projected to plane normal to up (horizontal plane)
Vector3 forwardCurrent = transform.forward
- Vector3.Dot(transform.forward,Vector3.up) * Vector3.up;
// Debug to view forwardCurrent
Debug.DrawRay(transform.location, forwardCurrent, Color.white, 0f, false);
// create rotation based on forward
Quaternion targetRotation = Quaternion.LookRotation(forwardCurrent);
// rotate based on yaw, then pitch, then roll.
// This order prevents changes to the projected forward direction
targetRotation = targetRotation * Quaternion.AngleAxis(yaw, Vector3.up);
// Debug to see forward after applying yaw
Debug.DrawRay(transform.location, targetRotation * Vector3.forward, Color.red, 0f, false);
targetRotation = targetRotation * Quaternion.AngleAxis(pitch, Vector3.right);
targetRotation = targetRotation * Quaternion.AngleAxis(roll, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth);
//debug new forward/up
Debug.DrawRay(transform.location, Transform.forward, Color.blue, 0f, false);
Debug.DrawRay(transform.location, Transform.up, Color.green, 0f, false);
controller.Move(moveDirection * Time.deltaTime);
}
这可以被认为是部分答案,因为能够确定“展平”的方向并重新排列应用组件旋转的过程对于回答您的问题很有用,但可能不足以获得所需的全部效果,具体取决于详细信息。
作为旁注,如果要确保它实际上会达到目标旋转而不是无限接近它,则可能要考虑使用Quaternion.RotateTowards
而不是Quaternion.Slerp
。