Unity3D切换摄像头模式 - 跟随FreeCam跳跃

时间:2017-04-20 09:16:05

标签: c# unity3d camera transform

我正在创建一个自定义相机来查看3D对象。相机通常是一个飞行摄像头,但在拖动物体时,我希望相机绕物体运行。我已经实现了这一点,但是在模式之间交换时相机会在两个位置之间跳跃。我如何平滑这一点,使相机在轨道后保持相同的位置,用户可以从这个位置继续飞行凸轮模式。这是我的代码:

    if (!rotateToggle)
    {
        if (Input.GetMouseButton(0)){
            rotationX += Input.GetAxis("Mouse X") * cameraSensitivity * Time.deltaTime;
            rotationY += Input.GetAxis("Mouse Y") * cameraSensitivity * Time.deltaTime;
        }
        rotationY = Mathf.Clamp(rotationY, -90, 90);

        transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
        transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);
        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
        {
            cameraSpeed = 150f;
        }
        else
        {
            cameraSpeed = 50f;
        }


        transform.position += transform.forward * cameraSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
        transform.position += transform.right * cameraSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
    }else{

        rotationX = Input.GetAxis("Mouse X") * RotateAmount;
        rotationY = Input.GetAxis("Mouse Y") * RotateAmount;

        Vector3 angles = transform.eulerAngles;
        angles.z = 0;
        transform.eulerAngles = angles;
        transform.RotateAround(rotationTarget.position, Vector3.up, rotationX);
        transform.RotateAround(rotationTarget.position, Vector3.left, -rotationY);
        transform.LookAt(rotationTarget);

    }
当用户拖动对象时,

rotateToggle为true,而rotationTarget是轨道目标的变换。

谢谢!

编辑:进一步调查时,它纯粹是旋转角度,而不是前面所述的实际位置!再次感谢

Edit2:为了进一步说明,我希望能够保持以下各项之间的轮换值:

transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);

            transform.eulerAngles = angles;
            transform.RotateAround(rotationTarget.position, Vector3.up, rotationX);
            transform.RotateAround(rotationTarget.position, Vector3.left, -rotationY);
            transform.LookAt(rotationTarget);
交换相机模式时

2 个答案:

答案 0 :(得分:1)

这可以使用Vector3.Lerp和Coroutines来实现。

每当您的rotateToggle-flag更改其值时 - 可能是在按下按钮或单击鼠标时 - 启动协程(有关coroutines here的更多信息)并使用Vector3.Lerp(或Quaternion)插入位置和旋转。 Lerp for Rotations也可以工作 - 链接到Vector3.Lerp文档here)。因此,您将在两个状态之间实现平滑过渡,并且还可以调整过渡所需的时间。

虽然以这种方式拍摄相机的位置和旋转,但你应该a)锁定用户的unteractions和b)不执行你的问题中发布的代码,因为它们会干扰协程(上面的代码会设置旋转并立即定位到“结束状态”,而协程将其设置为变量“过渡状态”。)

不幸的是,我现在手边没有示例代码。

答案 1 :(得分:0)

我能够通过混淆一些lerps并允许速度不断增加来解决这个问题:

        if (!rotateToggle)
        {
            if (Input.GetMouseButton(0))
            {
                rotationX += Input.GetAxis("Mouse X") * cameraSensitivity * Time.deltaTime;
                rotationY += Input.GetAxis("Mouse Y") * cameraSensitivity * Time.deltaTime;
            }

            rotationY = Mathf.Clamp(rotationY, -90, 90);

            transform.localRotation = transform.localRotation * Quaternion.AngleAxis(rotationX, Vector3.up);
            transform.localRotation = transform.localRotation * Quaternion.AngleAxis(rotationY, Vector3.left);
            transform.localRotation = Quaternion.Euler(transform.localRotation.eulerAngles.x, transform.localRotation.eulerAngles.y, 0);

            if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
            {
                cameraSpeed = 150f;
            }
            else
            {
                cameraSpeed = 50f;
            }


            transform.position += transform.forward * cameraSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
            transform.position += transform.right * cameraSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
            rotationX = Mathf.Lerp(rotationX, 0f, 0.1f);
            rotationY = Mathf.Lerp(rotationY, 0f, 0.1f);

        }
        else
        {

            rotationX = Input.GetAxis("Mouse X") * RotateAmount;
            rotationY = Input.GetAxis("Mouse Y") * RotateAmount;

            Vector3 angles = transform.eulerAngles;
            angles.z = 0;
            transform.eulerAngles = angles;
            transform.RotateAround(rotationTarget.position, Vector3.up, rotationX);
            rotationY = Mathf.Clamp(rotationY, -30, 30);

            transform.RotateAround(rotationTarget.position, Vector3.left, -rotationY);
            transform.localRotation = Quaternion.Euler(transform.localRotation.eulerAngles.x, transform.localRotation.eulerAngles.y, 0);
        }

我还添加了一个lookat协程以平滑过渡:

IEnumerator LerpToTarget()
{
    float time = 0;
    while (time < 0.1f)
    {
        Vector3 pos = rotationTarget.transform.position-transform.position;
        var newRot = Quaternion.LookRotation(pos);
        transform.rotation = Quaternion.Lerp(transform.rotation, newRot, 0.1f);
        time += Time.deltaTime;
        yield return null;
    }
    StartCoroutine(LookAtTarget());

}

IEnumerator LookAtTarget()
{
    while (rotateToggle)
    {
        transform.LookAt(rotationTarget);
        yield return null;
    }
}

这绝对可以改善,因为上下轨道仍然存在一些问题。