【问题标题】:Rotating towards a final rotation challenge轮流走向最后的轮换挑战
【发布时间】:2022-01-16 21:35:16
【问题描述】:

考虑这个处理 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() 的工作感觉有点hacky,但有没有另一种方法可以将相机设置为强制旋转,以保持子对象(相机所在的位置)的局部旋转为0?

我想分解由Quaternion.Lerp(transform.rotation, pivot.rotation, 0.05f); 在它们各自的轴和游戏对象中的每个轴和游戏对象中的Quaternion.Lerp(transform.rotation, pivot.rotation, 0.05f); 给出的下一步旋转,因为它在从输入设置旋转时完成,以便在其中有一个干净的局部Y rot他的相机游戏对象每一步。在这种情况下似乎是过于复杂的事情,但无法弄清楚。

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

【问题讨论】:

    标签: c# unity3d rotation quaternions


    【解决方案1】:

    这会让camera看方向,父transform看方向,只是flattened,最后根据两者的区别更新内部状态(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);
        }
    

    【讨论】:

    • 谢谢你的回答,我试试看
    • @rustyBucketBay 你试过了吗?
    • 这与我认为的更优雅的方式相同,即使用提到的 FPS 规则应用旋转。为了添加我在示例中使用的渐进式旋转,我刚刚添加了Vector3 nextDir = Vector3.RotateTowards(transform.forward, target.forward, Mathf.PI/360, 1);,然后使用nextDir 参数调用您的方法。这很有效,很有意义,非常感谢!
    猜你喜欢
    • 2020-11-27
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多