转向最后的轮换挑战

Rotating towards a final rotation challenge

考虑这个处理 FPS 相机移动的工作脚本:

using UnityEngine;

public class CameraHandler : MonoBehaviour {
    public Transform target;
    float dragSpeed = 10f;
    float lookAtSensitivity = 200f;
    float xRot;
    Transform parentGO;

    private void Start() {
        parentGO = transform.parent;
    }
    void goToPivot(Transform pivot) {
        parentGO.position = Vector3.Lerp(transform.position, pivot.position, 0.05f);
        transform.rotation = Quaternion.Lerp(transform.rotation, pivot.rotation, 0.05f);
    }

    void resetCamRot() {
        xRot = 0;
        float yRot = transform.localEulerAngles.y;
        parentGO.transform.eulerAngles += new Vector3(0, yRot, 0);
        transform.localEulerAngles -= new Vector3(0, yRot, 0);
    }

    void LateUpdate() {
        if (Input.GetKey(KeyCode.Mouse1)) {  
            float touchX = Input.GetAxis("Mouse X") * lookAtSensitivity * Time.deltaTime;
            float touchY = Input.GetAxis("Mouse Y") * lookAtSensitivity * Time.deltaTime;
            xRot -= touchY;
            xRot = Mathf.Clamp(xRot, -90f, 90f);
            transform.localRotation = Quaternion.Euler(xRot, 0f, 0f);
            parentGO.transform.Rotate(Vector3.up * touchX);
            
        }

        if (Input.GetKey(KeyCode.Space)) {
            goToPivot(target);
        }
        if (Input.GetKeyUp(KeyCode.Space)) {
            resetCamRot();
        }
    }
}

检查不同游戏对象在各自轴上的旋转方式,以便每个旋转保持独立并且一切正常。

transform.localRotation = Quaternion.Euler(xRot, 0f, 0f); //camera GO only rotates in local x
parentGO.transform.Rotate(Vector3.up * touchX); //parent GO only rotates in global y

当我需要在没有输入的情况下“强制”相机朝某个方向看时,就会出现问题,这会破坏 FPS 移动规则,例如相机游戏对象也在 Y 轴上旋转。这就是为什么我需要调用 resetCamRot() 方法,并将相机对象的局部旋转传递给父对象,以便满足 FPS 运动要求(无局部 Y 轴旋转)。

在不调用 resetCamRot() 方法的情况下,当单击鼠标右键开始 FPS 移动时,相机突然改变到它在使用 goToPivot 设置位置和旋转。(只需注释掉 resetCamRot 方法)

虽然 resetCamRot() 做的工作感觉有点老套,但是还有另一种方法可以将相机设置为强制旋转,从而将子对象(相机所在的位置)的局部旋转保持为 0 吗?

我想分解由 Quaternion.Lerp(transform.rotation, pivot.rotation, 0.05f);goToPivot() 方法中的每个轴和 gameObjects 给出的下一步旋转,就像从输入设置旋转时所做的那样,有每一步在他的相机游戏对象中都有一个干净的本地 Y 旋转。在这种情况下似乎是过于复杂的事情,但无法弄清楚。

如果您想尝试脚本来应对挑战,只需将父游戏对象添加到相机并在编辑器中附加目标即可。

这将使相机朝一个方向看,父变换朝一个方向看,仅展平,最后根据两者的区别更新内部状态(xRot):

    void LookTowards(Vector3 direction) {
        Vector3 flattened = direction;
        flattened.y = 0f;

        parentGo.rotation = Quaternion.LookRotation(flattened);
        transform.rotation = Quaternion.LookRotation(direction);
        xRot = Vector3.SignedAngle(flattened, direction, parentGo.right);
    }