Want more features? Check out the with advanced orbit camera with lock-on targeting, shoulder swap, cinematic mode, and swappable camera profiles for versatile third person gameplay.
intermediate Movement

Third Person Camera

Orbit camera with collision detection, zoom, and vertical angle limits. Ideal for action-adventure and RPG games.

Unity 2022.3+ · 3.6 KB · ThirdPersonCamera.cs

How to Use

1

Create an empty CameraRig object and parent your Camera to it

2

Attach ThirdPersonCamera to the CameraRig

3

Assign your player Transform as the Target

4

Adjust distance, zoom range, and rotation speed

5

Set collision layers to avoid clipping through walls

6

Camera auto-avoids obstacles via SphereCast

Source Code

ThirdPersonCamera.cs
C#
using UnityEngine;

/// <summary>
/// Third person orbit camera with collision avoidance.
/// Attach to an empty CameraRig object, parent your Camera as a child.
/// </summary>
public class ThirdPersonCamera : MonoBehaviour
{
    [Header("Target")]
    [SerializeField] private Transform target;
    [SerializeField] private Vector3 targetOffset = new Vector3(0f, 1.5f, 0f);

    [Header("Orbit")]
    [SerializeField] private float rotationSpeed = 5f;
    [SerializeField] private float minVerticalAngle = -30f;
    [SerializeField] private float maxVerticalAngle = 70f;

    [Header("Distance")]
    [SerializeField] private float defaultDistance = 5f;
    [SerializeField] private float minDistance = 1.5f;
    [SerializeField] private float maxDistance = 15f;
    [SerializeField] private float zoomSpeed = 3f;
    [SerializeField] private float zoomSmoothing = 8f;

    [Header("Collision")]
    [SerializeField] private float collisionRadius = 0.3f;
    [SerializeField] private LayerMask collisionLayers = ~0;

    [Header("Smoothing")]
    [SerializeField] private float followSmoothing = 10f;

    private float currentX;
    private float currentY = 15f;
    private float currentDistance;
    private float targetDistance;
    private Camera cam;

    private void Awake()
    {
        cam = GetComponentInChildren<Camera>();
        currentDistance = defaultDistance;
        targetDistance = defaultDistance;
    }

    private void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    private void LateUpdate()
    {
        if (target == null) return;

        HandleInput();
        UpdatePosition();
    }

    private void HandleInput()
    {
        if (Cursor.lockState != CursorLockMode.Locked) return;

        currentX += Input.GetAxis("Mouse X") * rotationSpeed;
        currentY -= Input.GetAxis("Mouse Y") * rotationSpeed;
        currentY = Mathf.Clamp(currentY, minVerticalAngle, maxVerticalAngle);

        float scroll = Input.GetAxis("Mouse ScrollWheel");
        if (Mathf.Abs(scroll) > 0.01f)
        {
            targetDistance -= scroll * zoomSpeed;
            targetDistance = Mathf.Clamp(targetDistance, minDistance, maxDistance);
        }
    }

    private void UpdatePosition()
    {
        currentDistance = Mathf.Lerp(currentDistance, targetDistance, Time.deltaTime * zoomSmoothing);

        Vector3 focusPoint = target.position + targetOffset;
        Quaternion rotation = Quaternion.Euler(currentY, currentX, 0f);
        Vector3 desiredPosition = focusPoint + rotation * new Vector3(0f, 0f, -currentDistance);

        // Collision check
        float adjustedDistance = currentDistance;
        Vector3 direction = desiredPosition - focusPoint;

        if (Physics.SphereCast(focusPoint, collisionRadius, direction.normalized,
            out RaycastHit hit, currentDistance, collisionLayers))
        {
            adjustedDistance = hit.distance - collisionRadius;
            adjustedDistance = Mathf.Max(adjustedDistance, minDistance * 0.5f);
        }

        Vector3 finalPosition = focusPoint + rotation * new Vector3(0f, 0f, -adjustedDistance);
        transform.position = Vector3.Lerp(transform.position, finalPosition, Time.deltaTime * followSmoothing);
        transform.LookAt(focusPoint);
    }

    /// <summary>
    /// Set a new target to follow at runtime.
    /// </summary>
    public void SetTarget(Transform newTarget)
    {
        target = newTarget;
    }
}
Ready for more? Third Person Camera Pro Advanced orbit camera with lock-on targeting, shoulder swap, cinematic mode, and swappable camera profiles for versatile third person gameplay.