c# - Quaternion.Slerp 在没有 Y 轴的 X 和 Z 轴上

标签 c# unity3d

Quaternion Rotation我正在尝试围绕 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 永远不会改变为摄像机 View /玩家 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);
    }

最佳答案

在引导我沿着不同的途径进行进一步研究之后,我发现有两个问题。这两个问题都围绕着这样一个事实,即 Z 轴在旋转后从未被标准化为新的 Y 轴度数。 @Ruzihm,解决了旋转问题。我解决了当时可见的运动问题。一旦旋转正常工作,它就会变得很容易看到。

本质上,在 Y 轴旋转 (Vector3.up) 发生任何变化后,必须重新计算 Z 轴 (transform.forward)。有了新法线 (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);

关于c# - Quaternion.Slerp 在没有 Y 轴的 X 和 Z 轴上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56878359/

相关文章:

c# - 将字符串时间格式化为短时间格式

ios - 将值从统一 3D 传递到 objective-c 文件

c# - 在 Unity 中序列化多个变量的更简洁方法

c# - 当我是 "drawing"线时,如何将点平均分配到 LineRenderer 的宽度曲线?

c# - 使用 bouncycaSTLe 将加密/解密从 Java 转换为 C#

c# - 注册多个 DbContext 时,如何解析 ConfigureServices 中正确的 DbContext 类型

c# - 将 html 字符串写入 csv 文件

c# - 状态码不成功时无法读取HttpResponseMessage内容

c# - 短时间显示文本层

c# - 如何使用不带属性的 SelectNode() 检索 XML 节点列表?