[Solved ]Zoom Main Camera Smoothly

Objective

I want to zoom the main camera by changing the field of view, and I want it to happen smoothly.

Problem

I am getting the zoom in, but it is too fast. I have change variables and played with number but still is either too fast or it does not happen.

Code


public class ZoomInOut : MonoBehaviour {

    //public variables parameter for Unity inspector input
    public float initialFOV;
    public float zoomInFOV;
    public float smooth;

    //private variables for script mod
    private float sphereRotation;
    private float lerpTimer;

	// Use this for initialization
	void Start ()
    {
        Camera.main.fieldOfView = initialFOV;
    }
	
	// Update is called once per frame
	void Update ()
    {
            ChangeFOV();
	}

    void ChangeFOV()
    {
        lerpTimer = Time.deltaTime * smooth;
        Camera.main.fieldOfView = Mathf.Lerp(initialFOV, zoomInFOV, lerpTimer);
    }
}

Thanks in advance!

In case you would like to know how I solved it.

Objective

  1. Check when rotation stopped
  2. Change the FOV to the Zoom-In parameter
  3. Make the change in an incremental smooth manner

Solution

Instead of using mathf.lerp I changed to if statements. I started checking what was the current FOV after rotation stopped. When it started to Zoom-In I checked the FOV until it was the same or smaller than my Zoom-In value, at which point I set it equal to my Zoom-In input. I change the value of the FOV using an incremental.

Code


public class ZoomInOut : MonoBehaviour
{

    //public variables paremeters for Unity inpector inputs
    public float initialFOV;
    public float zoomInFOV;
    public float smooth;

    //private variables for script mod
    private float sphereRotation;
    private float currentFOV;

    // Use this for initialization
    void Start()
    {
        //set initial FOV at start
        Camera.main.fieldOfView = initialFOV;
    }

    // Update is called once per frame
    void Update()
    {
        //get component from sphere script to know if rations is happening
        sphereRotation = GameObject.Find("Sphere").GetComponent<Rotation>().rotationSpeed;
        
         //store current field of view value in variable
        currentFOV = Camera.main.fieldOfView;

        //check if roration stopped and call function to change FOV
        if (sphereRotation <= 0)
        {
            ChangeFOV();
        }
    }

    //function to zoom in the FOV
    void ChangeFOV()
    {
        //check that current FOV is different than Zoomed
        if (currentFOV != zoomInFOV)
        {
            //check if current FOV is grater than the Zoomed in FOV input and increment the FOV smoothly
            if (currentFOV > zoomInFOV)
            {
                Camera.main.fieldOfView += (-smooth * Time.deltaTime);
            }
            else
            {
                //then current FOV gets to the same or smaller value than the Zoomed in input
                //set FOV as the Zoomed in input
                if (currentFOV <= zoomInFOV)
                {
                    Camera.main.fieldOfView = zoomInFOV;
                }
            }
        }
    }
}

This was my solution to my problem. Please feel free to criticize and comment on it. I tried the math.lerp but I was not able to get the smooth transition I wanted. If you have a better way, you can post a working example.

Cheers

Here is a solution using Lerp with a few examples how to smooth it out. Just slap this script on a camera and it should work.

All that matters is in the 4 lines within the first if statement in the ChangeFOV() method. The magic is how you calculate t, the actual interpolation. I have 4 examples there: Smoothstep and SmootherStep smoothing in and out, quadratic and cubic just easing in (could be inverted to ease out).

using System;
using UnityEngine;

[RequireComponent(typeof(Camera))]
public class FoviLerp : MonoBehaviour {
    public float FovStart = 60;
    public float FovEnd = 30;
    public float TransitionTime = 3;

    private float _currentFov;
    private float _lerpTime;
    private Camera _camera;

    void Start ()
    {
        //could also use Camera.main if apropriate
        _camera = this.GetComponent<Camera>();
    }
	
	void Update () {
        ChangeFOV();
    }

    void ChangeFOV()
    {
        if (Math.Abs(_currentFov - FovEnd) > float.Epsilon)
        {
            _lerpTime += Time.deltaTime;
            var t = _lerpTime / TransitionTime;

            //Different ways of interpolation if you comment them all it is just a linear lerp
            t = Mathf.SmoothStep(0, 1, t); //Mathf.SmoothStep() can be used just like Lerp, here it is used to calc t so it works with the other examples.
            //t = SmootherStep(t);
            //t = t * t;
            //t = t * t * t;

            _currentFov = Mathf.Lerp(FovStart, FovEnd, t);
        }
        else if (Math.Abs(_currentFov - FovEnd) < float.Epsilon)
        {
            //Just going back where we came from. For demonstrative purpos only ...
            _lerpTime = 0;
            Debug.Log("Switch");
            var tmp = FovStart;
            FovStart = FovEnd;
            FovEnd = tmp;
        }

        _camera.fieldOfView = _currentFov;
    }

    private float SmootherStep(float t)
    {
        return t * t * t * (t * (6f * t - 15f) + 10f);
    }
}

Hey, you may find these videos helpful!

We complete a lot of scripts like this one on our channel, and we just happened to complete these fairly recently. Hope this helps!