团结 - 透过枪的范围

时间:2015-10-09 16:10:14

标签: unity3d camera zoom lerp

现在我有2个摄像头:主摄像头显示枪处于正常状态,第二个摄像头连接到枪上(枪是主摄像头的孩子),当切换时,它看起来是通过枪,增加了视野。

为了更好的理解,这是一个视觉效果:

enter image description here

enter image description here

现在,如果我只是打开第二台摄像机并关闭主摄像头,这将非常出色,但它并不是很理想。每个场景只能有1个摄像头。

因此,我希望Lerp相机的位置以查看示波器并手动减少fieldofview。所以我写了以下脚本:

[RequireComponent(typeof(Camera))]
public class Zoom : MonoBehaviour {

    private Transform CameraTransform = null;
    public Transform ZoomedTransform;

    private bool zoomed = false;

    void Start () {
        CameraTransform = Camera.main.transform;
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKey (KeyCode.LeftShift)) 
        {
            CameraTransform.position = Vector3.Lerp (
                CameraTransform.position, 
                CameraTransform.position + ZoomedTransform.position, 
                5f * Time.deltaTime
            );
            CameraTransform.Rotate(ZoomedTransform.rotation.eulerAngles);
        }
    }
}

问题在于它不起作用:当我按下变焦按钮时,相机以光速在场景中加速,并且很难确切地知道发生了什么。

有人能给我一些关于我做错了什么的见解吗?我认为这与父子关系有关,但即使我尝试使用静态值,我似乎无法复制正确的解决方案。

层次:

enter image description here

2 个答案:

答案 0 :(得分:1)

你的lerp目标是相对于相机的当前位置,所以它不断移动。这是你的目标:

CameraTransform.position + ZoomedTransform.position

这意味着当相机移动到接近此位置时,相机的新位置会导致目的地发生变化。所以你的相机一直在移动。

您的目的地应为ZoomedTransform.position。因position is in world coordinates而无需添加。 (当你真的需要在空格之间进行转换时,请查看TransformPoint和类似的方法。)

答案 1 :(得分:1)

(这个答案是在假设ZoomedTransform是相对转换的情况下运行的,而不是31eee384的回答所怀疑的相机的绝对位置。)

我认为您的代码存在一些问题。我会单独处理它们,这样它们更容易理解,但它们都与以下几行有关:

CameraTransform.position = Vector3.Lerp (CameraTransform.position, CameraTransform.position + ZoomedTransform.position, 5f * Time.deltaTime);

首先,让我们看看你如何使用Vector3.Lerp()。对于Vector3.Lerp()的第三个参数,您提供5f * Time.deltaTime。这个价值究竟到底是什么?那么,标准帧率约为60 FPS,因此Time.deltaTime = ~1 / 60。因此,5f * Time.deltaTime = 5/60 = ~0.0833。

Vector3.Lerp()期望第三个参数是什么?根据{{​​3}},第三个参数应该在0和1之间,并确定返回的Vector3是否应该更靠近第一个或第二个Vector3。所以是的,5f * Time.deltaTime落在这个范围内,但不会发生插值 - 因为它总是在~0.0833左右,而不是从0进展到1(或1到0)。每一帧,你基本上都会回来cameraPos + zoomTransform * 0.0833

另一个值得注意的问题是你如何每帧更新CameraTransform.position的值,然后使用新的(增加的)值作为下一帧Vector3.Lerp()的参数。 (这有点像在循环中执行int i = i + 1;。)这就是为什么你的相机如此快速地飞越地图的原因。以下是每帧的情况,使用我之前计算的Vector3.Lerp()的假设结果(伪代码):

// Frame 1
cameraPosFrame_1 = cameraPosFrame_0 + zoomTransform * 0.0833;
// Frame 2
cameraPosFrame_2 = cameraPosFrame_1 + zoomTransform * 0.0833;
// Frame 3
cameraPosFrame_3 = cameraPosFrame_2 + zoomTransform * 0.0833;
// etc...

每一帧zoomTransform * 0.0833都会被添加到相机的位置。最终真正,快速,不间断地增加价值 - 所以你的相机飞过地图。

解决这些问题的一种方法是使用变量来存储相机的初始本地位置,缩放进度和缩放速度。这样,我们永远不会丢失相机的原始位置,我们可以跟踪变焦进展的距离以及何时停止它。

[RequireComponent(typeof(Camera))]
public class Zoom : MonoBehaviour {

    private Transform CameraTransform = null;
    public Transform ZoomedTransform;
    private Vector3 startLocalPos;
    private float zoomProgress = 0;
    private float zoomLength = 2; // Number of seconds zoom will take

    private bool zoomed = false;

    void Start () {
        CameraTransform = Camera.main.transform;
        startLocalPos = CameraTransform.localPosition;
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKey (KeyCode.LeftShift)) 
        {
            zoomProgress += Time.deltaTime;

            CameraTransform.localPosition = Vector3.Lerp (startLocalPos, startLocalPos + ZoomedTransform.position, zoomProgress / zoomLength);
            CameraTransform.Rotate(ZoomedTransform.rotation.eulerAngles);
        }
    }
}

希望这有帮助!如果您有任何疑问,请告诉我。这个答案确实有些絮絮叨叨,所以我希望你从中获得重点不会有任何麻烦。

相关问题