如何为 transform.rotatearound Unity 限制(夹紧)Y 轴旋转

How to Limit (clamp) Y axis Rotation for transform.rotatearound Unity

我有一个相机,我想围绕一个点 (0,0,0) 在所有方向上旋转,但我想在它上面放一个夹子,这样它就不会在观点。我以前见过这个问题针对左右方向的回答,但从未针对垂直方向回答过。

我已经尝试将这两个问题的代码(基本上说的是同一件事)转换为在垂直方向上工作,但是它在旋转的某些点上出现错误,我不明白为什么。

First Question, Second Question

这就是我尝试转换它的方式:

//how much we want to rotate by this frame
float rotX = Input.GetAxis("Mouse X") * rotSpeed;
float rotY = Input.GetAxis("Mouse Y") * rotSpeed; //(before clamping)

//find current direction
Vector3 currentDirection = transform.position - Vector3.zero;

//find current angle between basis for clamp & where we are now
float angle = Vector3.Angle(Vector3.forward, currentDirection);

 //finds out if it's up or down
if (Vector3.Cross(Vector3.forward, currentDirection).x < 0) angle = -angle; 

 //find out how much you can move without violating limits
 float newAngle = Mathf.Clamp(angle + rotY, yMinLimit, yMaxLimit);

//grabs how much you are allowed to move the angle from the current angle
rotY = newAngle - angle;

//spinning the garden
transform.RotateAround(Vector3.zero, Vector3.up, rotX);
 transform.RotateAround(Vector3.zero, transform.TransformDirection(Vector3.right), -rotY); //vertical rotation

如果有人知道使它适用于 Y 轴的正确方法,或者夹住垂直旋转的不同方法,我会非常高兴听到它!泰!

我这里有一个 class 可以完全满足您的需求。它围绕目标旋转相机并固定 Y 旋转。它使用左键旋转和滚动按钮平移目标。 您可以对其进行编辑以适应您的特定需求——您可能希望将目标更改为 Vector3,以便无需对象即可将其设置为 (0,0,0)。希望能帮助到你。

using UnityEngine;


public class RotateAroundCamera : MonoBehaviour
{
    Camera cam;
    public bool isControlable;
    private Vector3 screenPoint;
    private Vector3 offset;
    public Transform target;
    public float distance = 5.0f;
    public float xSpeed = 50.0f;
    public float ySpeed = 50.0f;

    public float yMinLimit = -80f;
    public float yMaxLimit = 80f;

    public float distanceMin = .5f;
    public float distanceMax = 15f;

    public float smoothTime = 2f;

    public float rotationYAxis = 0.0f;
    float rotationXAxis = 0.0f;

    float velocityX = 0.0f;
    float velocityY = 0.0f;
    float moveDirection = -1;

    public void SetControllable(bool value)
    {
        isControlable = value;
    }

    // Use this for initialization
    void Start()
    {
        cam = GetComponentInChildren<Camera>();
        Vector3 angles = transform.eulerAngles;
        rotationYAxis = (rotationYAxis == 0) ? angles.y : rotationYAxis;
        rotationXAxis = angles.x;

        Rigidbody rigidbody = GetComponent<Rigidbody>();

        // Make the rigid body not change rotation
        if (rigidbody)
        {
            rigidbody.freezeRotation = true;
        }
    }

    void LateUpdate()
    {
        if (target)
        {
            if (Input.GetMouseButton(1) && isControlable)
            {
                velocityX += xSpeed * Input.GetAxis("Mouse X") * 0.02f;
                velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
            }


            if (Input.GetMouseButton(2) && isControlable)
            {
                Vector3 curScreenPoint = new Vector3(moveDirection*Input.mousePosition.x, moveDirection*Input.mousePosition.y, screenPoint.z);

                Vector3 curPosition = cam.ScreenToWorldPoint(curScreenPoint) + offset;
                target.transform.position = curPosition;
            }

            if (Input.GetKeyDown(KeyCode.R) && isControlable)
            {
                target.transform.position = Vector3.zero;
            }

            if (Input.GetKeyDown(KeyCode.T) && isControlable)
            {
                moveDirection *= -1;
            }

            if (isControlable)
            {
                distance -= Input.GetAxis("Mouse ScrollWheel");

                if (distance > distanceMax)
                {
                    distance = distanceMax;
                }
                else if (distance < distanceMin)
                {
                    distance = distanceMin;
                }
            }

            rotationYAxis += velocityX;
            rotationXAxis -= velocityY;

            rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);

            Quaternion fromRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, 0);
            Quaternion toRotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
            Quaternion rotation = toRotation;

            Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
            Vector3 position = rotation * negDistance + target.position;

            transform.rotation = rotation;
            transform.position = position;

            velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
            velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);

            screenPoint = cam.WorldToScreenPoint(target.transform.position);
            offset = target.transform.position - cam.ScreenToWorldPoint(new Vector3(moveDirection*Input.mousePosition.x, moveDirection*Input.mousePosition.y, screenPoint.z));
        }

    }

    public static float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360F)
            angle += 360F;
        if (angle > 360F)
            angle -= 360F;
        return Mathf.Clamp(angle, min, max);
    }
}