Part of these game systems:
intermediate Touch & Mobile

Pinch-to-Zoom Camera

Smooth pinch-to-zoom camera control for mobile devices supporting both orthographic and perspective cameras. Features configurable zoom limits and optional smoothing.

Unity 2022.3+ · 3.0 KB · PinchToZoomCamera.cs

How to Use

1

Attach the PinchToZoomCamera script to your Main Camera

2

Set minZoom and maxZoom limits in the inspector

3

Enable autoDetectMode to automatically configure for orthographic or perspective

4

Adjust zoomSpeed and smoothSpeed to taste

5

Test with two-finger pinch on a mobile device or use Remote in the editor

Source Code

PinchToZoomCamera.cs
C#
using UnityEngine;

public class PinchToZoomCamera : MonoBehaviour
{
    [Header("Zoom Settings")]
    [SerializeField] private float zoomSpeed = 0.5f;
    [SerializeField] private float minZoom = 2f;
    [SerializeField] private float maxZoom = 20f;

    [Header("Smoothing")]
    [SerializeField] private bool enableSmoothing = true;
    [SerializeField] private float smoothSpeed = 8f;

    [Header("Camera Mode")]
    [SerializeField] private bool autoDetectMode = true;

    private Camera cam;
    private float targetZoom;
    private float previousTouchDistance;
    private bool isPinching;

    private void Awake()
    {
        cam = GetComponent<Camera>();
        if (cam == null)
            cam = Camera.main;

        if (autoDetectMode)
        {
            minZoom = cam.orthographic ? 1f : 20f;
            maxZoom = cam.orthographic ? 30f : 100f;
        }

        targetZoom = cam.orthographic ? cam.orthographicSize : cam.fieldOfView;
    }

    private void Update()
    {
        HandlePinchInput();
        ApplyZoom();
    }

    private void HandlePinchInput()
    {
        if (Input.touchCount == 2)
        {
            Touch touch0 = Input.GetTouch(0);
            Touch touch1 = Input.GetTouch(1);

            float currentDistance = Vector2.Distance(touch0.position, touch1.position);

            if (!isPinching)
            {
                isPinching = true;
                previousTouchDistance = currentDistance;
                return;
            }

            float delta = previousTouchDistance - currentDistance;
            float zoomDelta = delta * zoomSpeed * Time.deltaTime;

            targetZoom += zoomDelta;
            targetZoom = Mathf.Clamp(targetZoom, minZoom, maxZoom);

            previousTouchDistance = currentDistance;
        }
        else
        {
            isPinching = false;
        }

        // Mouse scroll fallback for editor testing
        float scroll = Input.GetAxis("Mouse ScrollWheel");
        if (Mathf.Abs(scroll) > 0.01f)
        {
            targetZoom -= scroll * zoomSpeed * 100f * Time.deltaTime;
            targetZoom = Mathf.Clamp(targetZoom, minZoom, maxZoom);
        }
    }

    private void ApplyZoom()
    {
        if (cam.orthographic)
        {
            if (enableSmoothing)
                cam.orthographicSize = Mathf.Lerp(cam.orthographicSize, targetZoom, Time.deltaTime * smoothSpeed);
            else
                cam.orthographicSize = targetZoom;
        }
        else
        {
            if (enableSmoothing)
                cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, targetZoom, Time.deltaTime * smoothSpeed);
            else
                cam.fieldOfView = targetZoom;
        }
    }

    public void SetZoom(float zoom)
    {
        targetZoom = Mathf.Clamp(zoom, minZoom, maxZoom);
    }

    public void ResetZoom()
    {
        targetZoom = cam.orthographic ? 5f : 60f;
    }

    public float GetCurrentZoom()
    {
        return cam.orthographic ? cam.orthographicSize : cam.fieldOfView;
    }

    public float GetZoomNormalized()
    {
        float current = GetCurrentZoom();
        return Mathf.InverseLerp(minZoom, maxZoom, current);
    }
}
Ready for more? Gyroscope Camera Controller Controls camera rotation using the device gyroscope sensor with smoothing and sensitivity settings.