0

我目前正在使用 Unity 游戏引擎创建一个 3D 平台游戏,我正在关注本教程系列以获得一些基本的玩家运动:https ://www.youtube.com/watch?v=h2d9Wc3Hhi0&list=PLiyfvmtjWC_V_H-VMGGAZi7n5E0gyhc37 。在我完成教程的运动部分后,我遇到了一个问题。每当我将鼠标移动到旋转阈值时,相机都会避开阈值并围绕 y 轴旋转。旋转后,鼠标输入反转。这是我的相机控制器代码:

using UnityEngine;

namespace Player
{
    public class CameraController : MonoBehaviour
    {
        public Transform target;
        public Transform orientation;
        public Vector3 offset;
        public bool useOffsetValues;
        public float sensitivity;
        public float maxViewAngle = 85;
        public float minViewAngle = -75;
        public bool invertY;

        private void Start()
        {
            if (!useOffsetValues)
            {
                offset = target.position - transform.position;
            }

            orientation.position = target.position;
            orientation.parent = null;

            Cursor.lockState = CursorLockMode.Locked;
        }

        private void LateUpdate()
        {
            orientation.position = target.position;

            float yaw = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime;
            orientation.Rotate(0, yaw, 0);

            float pitch = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime;
            if (invertY) orientation.Rotate(pitch, 0, 0);
            else orientation.Rotate(-pitch, 0, 0);

            if (orientation.rotation.eulerAngles.x > maxViewAngle && orientation.rotation.eulerAngles.x < 180)
            {
                orientation.rotation = Quaternion.Euler(maxViewAngle, orientation.eulerAngles.y, 0);
            }
            if (orientation.rotation.eulerAngles.x < 360 + minViewAngle && orientation.rotation.eulerAngles.x > 180)
            {
                orientation.rotation = Quaternion.Euler(360 + minViewAngle, orientation.eulerAngles.y, 0);
            }

            float yAngle = orientation.eulerAngles.y;
            float xAngle = orientation.eulerAngles.x;
            Quaternion rot = Quaternion.Euler(xAngle, yAngle, 0);
            transform.position = target.position - (rot * offset);

            if (transform.position.y < target.position.y - 0.5f)
            {
                transform.position = new Vector3(transform.position.x, target.position.y - 0.5f, transform.position.z);
            }

            transform.LookAt(target);
        }
    }
}

任何帮助,将不胜感激!

4

1 回答 1

0

首先,不要乘以GetAxis(mouse_axis_name)增量时间。GetAxis(mouse_axis_name)返回一个距离,乘以 delta 时间并没有多大意义。只需使用float yaw = Input.GetAxis("Mouse X") * sensitivity;andfloat pitch = Input.GetAxis("Mouse Y") * sensitivity; 即可避免因更改帧速率而引起的问题

其次,不是比较欧拉角分量,而是更容易简单地钳制pitch到不会导致旋转超出范围的范围,Vector3.Angle用于计算角度并Mathf.Clamp进行钳制。这解释了从欧拉角到Transform的内部Quaternion表示之间的信息丢失。为此,请设置最小上下角度。这些越大,相机对某些角度的约束就越大。

第三,偏移量应该只是一个距离,以避免它与相机的旋转角度发生冲突。

第四,您可以将 aQuaternion localRotation用于相机的状态,而不是使用 whole Transform,它会执行一些您甚至不使用的额外内容。用于Quaternion.Euler(0f, yaw, 0f) * desiredRotation * Quaternion.Euler(pitch, 0f, 0f)围绕全局向上yaw和局部向右旋转四元数pitch,然后desiredRotation * Vector3.forward找到旋转想要产生的正向。用于Quaternion.LookRotation将其初始化为使相机注视目标的旋转。

共:

[SerializeField] Transform target;
[SerializeField] float offset;
[SerializeField] bool useOffsetValues;
[SerializeField] float sensitivity;
[SerializeField] float minUpAngle = 5f;
[SerializeField] float minDownAngle = 5f;
[SerializeField] bool invertY;

Quaternion desiredRotation;

void Start()
{
    Vector3 positionDelta = target.position - transform.position;
    if (!useOffsetValues)
    {
        offset = positionDelta;
    }

    desiredRotation = Quaternion.LookRotation(positionDelta);
    Cursor.lockState = CursorLockMode.Locked;
}

void LateUpdate()
{
    float yaw = Input.GetAxis("Mouse X") * sensitivity;
    float pitch = Input.GetAxis("Mouse Y") * sensitivity;
    if (!invertY) pitch = -pitch;

    float angleForwardUp = Vector3.Angle(desiredRotation * Vector3.forward, Vector3.up);
    float angleForwardDown = 180f - angleForwardUp;

    float pitchMin = minUpAngle - angleForwardUp;
    float pitchMax = angleForwardDown - minDownAngle;

    pitch = Mathf.Clamp(pitch, pitchMin, pitchMax);

    desiredRotation = Quaternion.Euler(0f, yaw, 0f) * desiredRotation 
            * Quaternion.Euler(pitch, 0f, 0f);

    transform.position = target.position - (desiredRotation
            * Vector3.forward * offset);

    if (transform.position.y < target.position.y - 0.5f)
    {
        transform.position = new Vector3(transform.position.x,
                target.position.y - 0.5f,
                transform.position.z);
    }

    transform.LookAt(target);
}

于 2020-12-03T22:46:55.613 回答