【问题标题】:Unity3D Switching Camera Modes - Orbit to FreeCam JumpingUnity3D 切换相机模式 - Orbit 到 FreeCam Jumping
【发布时间】:2017-04-20 09:16:05
【问题描述】:

我正在创建一个自定义相机来查看 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 在用户拖动对象时为真,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);

切换相机模式时

【问题讨论】:

    标签: c# unity3d camera transform


    【解决方案1】:

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

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

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

    很遗憾,我现在手头没有示例代码。

    【讨论】:

    • 感谢您的回答,但在进一步调查中,不需要 lerping,在我的情况下,我只想保持两种相机模式之间的视角,因为位置已经保持。还是谢谢!
    【解决方案2】:

    我能够通过将一些 lerp 组合在一起并让速度不断增加来解决这个问题:

            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;
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-09
      • 2015-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多