2D Smooth Camera Movement
Just spent a long time figuring out a solution to this and thought I'd share/ask opinions; I need a function which I can call to zoom the camera centered on a specified point, I'm looking for a smooth motion so It needs to accelerate to a max speed then decelerate once it is close to the target. One big catch I'm struggling with is I want to be able to specify the transition time.
Answer by OutramJamie · Aug 28, 2020 at 09:27 PM
My solution was to calculating the area under a ramp up and down speed function to get the current distance along each frame: 
 
Behavior script with example use case shown here:
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Security.Cryptography;
 using UnityEditorInternal;
 using UnityEngine;
 
 public class CameraController : MonoBehaviour
 {
     //Place the camera to be moved in here
     public Camera selectedCamera;
 
     //Flag showing that the camera is moving
     public bool isCameraZooming { get; private set; }
     
     //All the information required to calculate the position and zoom
     private float originalSize;
     private float targetSize;
     private Vector2 originalPivot;
     private Vector2 targetPivot;
     private float transitionTime;
     private float remainingTime;
     private float rampTime;
 
     //Max speed values do not need to be calculated each frame
     private Vector2 _pivotVmax;
     private float _sizeVmax;
 
     private void Awake()
     {
         //Ensure the flag is initialized correctly
         isCameraZooming = false;
     }
 
     void Start()
     {
         //Example Zoom Trigger
         ZoomCameraWithRampUpDown(new Vector2(9, -9), 5f, 1f,0.5f);
     }
 
     // Update is called once per frame
     void Update()
     {
         if (isCameraZooming)
         {
             UpdateZoom();
         }
     }
 
     //Trigger for the camera movement
     public void ZoomCameraWithRampUpDown(Vector2 pivot, float size, float time, float rampTime)
     {
         if (isCameraZooming)
         {
             Debug.LogWarning("Camera already zooming");
             return;
         }
 
         //Set Values and Flags for zoom 
         this.originalSize = selectedCamera.orthographicSize;
         this.originalPivot = selectedCamera.transform.position;
         this.targetPivot = pivot;
         this.targetSize = size;
         this.transitionTime = time;
         this.remainingTime = time;
         this.rampTime = rampTime;
         this.isCameraZooming = true;
 
         //Calculate Max speed
         this._pivotVmax = CalcMaxSpeed(targetPivot - originalPivot, rampTime, transitionTime);
         this._sizeVmax = CalcMaxSpeed(targetSize - originalSize, rampTime, transitionTime);
 
     }
 
     //Calculates the peak velocity of the camera
     private float CalcMaxSpeed(float distance, float rampT, float transT)
     {
         if (transT <= 2 * rampT)
         {
             //If the ramp time is too large there is no middle platau
             //in this case the maximum speed reached is based on the total transition time i.e. rampTime = transitionTime/2
             return (2 * distance / transT);
         }
         else
         {
             return (distance / (transT - rampT));
         }
     }
     private Vector2 CalcMaxSpeed(Vector2 distance, float rampT, float transT)
     {
         return new Vector2(CalcMaxSpeed(distance.x, rampT, transT), CalcMaxSpeed(distance.y, rampT, transT));
     }
 
     //Method called every frame during zoom/movement
     private void UpdateZoom()
     {
         //Calculate new time independant of framerate
         remainingTime -= Time.deltaTime;
         float time = transitionTime - remainingTime;
 
         if(remainingTime<=0)
         {
             //if at the end of transition skip calculations
             selectedCamera.orthographicSize = targetSize;
             selectedCamera.transform.position = new Vector3(targetPivot.x, targetPivot.y, -10);
             //set flag at end of transition
             isCameraZooming = false;
         }
         
         //Calculate the new zoom and position values
         selectedCamera.orthographicSize = CalcRampedValue(originalSize, time, _sizeVmax);
         selectedCamera.transform.position = CalcRampedValue(originalPivot, time, _pivotVmax);
     }
     
     //Controls distance curve of zoom and position (t = 0 to transitiontime)
     private float CalcRampedValue(float startPoint, float t, float Vmax, float transT, float rampT)
     {
         //Ensure time given is within valid range
         t = Mathf.Clamp(t, 0, transT);
         
         
         double d = 0; //holds distance traveled
         //Depending on the given time select the correct calculations for distance
         if (t <= rampT)
         {
             //Ramp Up distance formula
             d = 0.5 / rampT * t * t;
         }
         else 
         {
             //Add Ramp Up total distance
             d += 0.5 * rampT; 
             if (t < transT - rampT)
             {
                 //Platau distance formula
                 d += (t - rampT);
             }
             else
             {
                 //Add Platau total distance
                 d += transT - 2 * rampT; 
                 //Ramp Down distance formula
                 d += 0.5 * (rampT - (transT - t)*(transT - t) / rampT);
             }
         }
         //Scale According to Max Velocity
         d *= Vmax;
         //Add starting Offset
         d += startPoint; 
         return (float)d;
     }
     float CalcRampedValue(float startPoint, float t, float Vmax)
     {
         return CalcRampedValue(startPoint, t, Vmax, transitionTime, rampTime);
     }
     Vector3 CalcRampedValue(Vector2 startPoint, float t , Vector2 Vmax)
     {
         return new Vector3(CalcRampedValue(startPoint.x, t, Vmax.x), CalcRampedValue(startPoint.y, t, Vmax.y), -10);
     }
 
 }
 
 
              Your answer
 
             Follow this Question
Related Questions
Camera moves impossibly fast, and can't see any object 1 Answer
Either my camera moves/changes size or my scene does... But why? Unity 2D 0 Answers
How to stop the camera when the player has reached the edge of the level? 2 Answers
How to mute sounds that are coming from game objects not in camera 1 Answer