【问题标题】:Issue with smooth camera zoom in UnityUnity 中相机平滑缩放的问题
【发布时间】:2019-03-18 20:54:52
【问题描述】:

我试图让我的相机在使用鼠标滚轮时平滑地放大和缩小,但由于某种原因它会立即放大而不是平滑地。

这就是我更新缩放的方式:

[SerializeField, Range(10, 100)] float scrollSpeed = 10f;
[SerializeField] Vector2 zoomAmount = Vector2.zero;

private float ScrollWheel
{
    get { return Input.GetAxis("Mouse ScrollWheel"); }
}

private new Camera camera = null;

void Update()
{
    if (camera == null) return;

    UpdateZoom();
}

void UpdateZoom()
{
    pos = camera.transform.position;

    pos = Vector3.Lerp(pos, new Vector3(pos.x, pos.y - scrollSpeed * 10 * ScrollWheel, pos.z), Time.deltaTime * 2);
    pos.y = Mathf.Clamp(pos.y, zoomAmount.x, zoomAmount.y);

    camera.transform.position = pos;
}

【问题讨论】:

    标签: c# unity3d camera zooming


    【解决方案1】:

    我认为您对Lerp 有点困惑(当我开始使用它时,我也有同样的困惑)。当您为时间参数(第三个参数)传入 0 时,它将返回您的“起始”向量。当您为 time 参数传递 1 或更大的值时,它将返回您的“结束”向量。 但是,如果您传递 Time.deltaTime * 2,那么您将在每一帧返回大致相同的插值向量。 Lerp 不会“跟踪”它已经插入了多远,因此通过每帧传递相同的时间值,Lerp 将永远不会真正返回您的结束向量。因此,与其通过Time.deltaTime * 2,您需要做这样的事情

    float interpolatedTime = 0;
    void Update()
    {
       var myVector = Vector3.Lerp(vector1, vector2, this.interpolatedTime);
       this.interpolatedTime += Time.deltaTime; 
    }
    

    这样的相机怎么样:

    float zoomTime;
    float zoomTarget;
    float lastScrollWheelDirection;
    
    void Update()
    {
        // If this camera is currently zooming in and the player started zooming
        // out (or vice versa), reset the amount that is remaining to be zoomed
        if ((this.lastScrollWheelDirection > 0 && this.ScrollWheel < 0) ||
            (this.lastScrollWheelDirection < 0 && this.ScrollWheel > 0))
        {
            this.zoomTarget = 0;
        }
        if (this.ScrollWheel != 0)
        {
            this.lastScrollWheelDirection = this.ScrollWheel;
        }
    
        // zoomTarget is the total distance that is remaining to be zoomed.
        // Each frame that the scroll wheel is moved, we'll add a little more
        // to the distance that we want to zoom
        zoomTarget += this.ScrollWheel * this.scrollSpeed;
    
        // zoomTime is used to do linear interpolation to create a smooth zoom.
        // Each time the player moves the mouse wheel, we reset zoomTime so that 
        // we restart our linear interpolation
        if (this.ScrollWheel != 0)
        {
            this.zoomTime = 0;
        }
    
        if (this.zoomTarget != 0)
        {
            this.zoomTime += Time.deltaTime;
    
            // Calculate how much our camera will be moved this frame using linear
            // interpolation.  You can adjust how fast the camera zooms by
            // changing the divisor for zoomTime
            var translation = Vector3.Lerp(
                new Vector3(0, 0, 0),
                new Vector3(0, this.zoomTarget, 0),
                zoomTime / 4f);   // see comment above
    
            // Zoom the camera by the amount that we calculated for this frame
            this.transform.position -= translation;
    
            // Decrease the amount that's remaining to be zoomed by the amount 
            // that we zoomed this frame
            this.zoomTarget -= translation.y;
        }
    }
    

    【讨论】:

    • 感谢您如此详细的回答! :) 现在整个 lerping 主题更加清晰。我实现了您的系统,它现在可以工作了,尽管有时如果我滚动得非常快,它会在某些点立即进入位置。现在好多了,但如果有道理的话,仍然感觉有点粗糙。
    • 嗯...你是什么意思它立即进入位置?如果您快速滚动,此代码将更快地缩放,但它应该始终缓和到最终位置。如果您希望它缩放得更慢,您可以增加 zoomTile 上的除数(示例中的 4f)。否则你能否就它做错了什么给出更多解释?当我测试它时,我没有经历任何瞬间跳跃。
    • 另外,当您快速滚动时,您是否可能向前滚动并意外向后滚动?一旦您开始向相反方向滚动,此代码将停止在当前方向上缩放;这看起来像是跳到了位置。如果您想消除这种行为,请注释掉代码中的顶部块(前两个 if 语句)。
    • 增加了除数,现在已经好多了!非常感谢您的帮助! :)
    猜你喜欢
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多