Daily free asset available! Did you claim yours today?

Mastering the Top-Down Camera in Unity: Smooth Movement, Zoom, and Collision Avoidance

Posted by Gemma Ellison
./
July 16, 2025

Want to build a strategy game, a puzzle experience, or an RPG with a bird’s-eye view? Mastering the top-down camera is absolutely crucial. But slapping a camera above your scene and calling it a day just won’t cut it. We need smooth movement, intuitive zoom, and, crucially, solutions to avoid clipping through walls. Let’s dive into crafting a robust and customizable top-down camera in Unity, complete with the code and the reasoning behind it.

Basic Camera Movement: The Foundation

The first step is getting the camera to follow the player (or any designated target). We’re going to control the camera’s position directly using a script.

Create a new C# script called TopDownCamera. Attach it to your main camera object in the Unity editor. The following code provides a basic “follow” behavior.

using UnityEngine;

public class TopDownCamera : MonoBehaviour
{
    public Transform target; // Assign the player (or target) in the Inspector
    public float height = 10f;
    public float distance = 5f;
    public float smoothSpeed = 7.5f;

    private Vector3 _offset;

    void Start()
    {
        _offset = new Vector3(0f, height, -distance);
    }

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

        Vector3 targetPosition = target.position + _offset;
        Vector3 smoothedPosition = Vector3.Lerp(transform.position, targetPosition, smoothSpeed * Time.deltaTime);
        transform.position = smoothedPosition;

        transform.LookAt(target);
    }
}

This script does the following:

  1. It declares a public target variable. Drag your player GameObject into this slot in the Inspector.
  2. It sets height and distance to control the initial camera position relative to the target.
  3. smoothSpeed is used to smoothly transition the camera’s position.
  4. In LateUpdate, which runs after all other updates, it calculates the desired camera position based on the target's position and the _offset.
  5. Vector3.Lerp provides a smooth transition.

Pitfall: Directly setting transform.position = target.position + offset; results in jarring, instant camera movement. Using Lerp is essential for a smooth, professional feel.

Implementing Zoom Functionality

A fixed camera distance is rarely ideal. Let’s add zoom functionality using the mouse wheel.

Modify the TopDownCamera script:

using UnityEngine;

public class TopDownCamera : MonoBehaviour
{
    public Transform target;
    public float height = 10f;
    public float distance = 5f;
    public float smoothSpeed = 7.5f;
    public float zoomSpeed = 5f;
    public float minDistance = 2f;
    public float maxDistance = 15f;

    private Vector3 _offset;

    void Start()
    {
        _offset = new Vector3(0f, height, -distance);
    }

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

        distance -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
        distance = Mathf.Clamp(distance, minDistance, maxDistance);
        _offset = new Vector3(0f, height, -distance); // Update offset based on new distance.

        Vector3 targetPosition = target.position + _offset;
        Vector3 smoothedPosition = Vector3.Lerp(transform.position, targetPosition, smoothSpeed * Time.deltaTime);
        transform.position = smoothedPosition;

        transform.LookAt(target);
    }
}

Key changes:

  1. Added zoomSpeed, minDistance, and maxDistance to control zoom behavior and limits.
  2. Input.GetAxis("Mouse ScrollWheel") detects mouse wheel input.
  3. Mathf.Clamp restricts the distance within the specified minDistance and maxDistance.
  4. Re-calculates the _offset to account for the new camera distance.

Now, scrolling the mouse wheel will zoom the camera in and out. The zoom speed and limits are adjustable in the Inspector, allowing for precise control.

Value-Added Insight: Don’t use Input.GetAxisRaw. The smoothed output of GetAxis provides a much more pleasing zoom experience.

Camera Collision Avoidance: No More Clipping!

Clipping through walls is a cardinal sin in game development. A simple yet effective solution is to use a raycast to detect obstacles and adjust the camera’s position accordingly.

Update the TopDownCamera script with the following:

using UnityEngine;

public class TopDownCamera : MonoBehaviour
{
    public Transform target;
    public float height = 10f;
    public float distance = 5f;
    public float smoothSpeed = 7.5f;
    public float zoomSpeed = 5f;
    public float minDistance = 2f;
    public float maxDistance = 15f;
    public LayerMask collisionLayers;

    private Vector3 _offset;

    void Start()
    {
        _offset = new Vector3(0f, height, -distance);
    }

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

        distance -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
        distance = Mathf.Clamp(distance, minDistance, maxDistance);
        _offset = new Vector3(0f, height, -distance);

        Vector3 targetPosition = target.position + _offset;
        Vector3 smoothedPosition = Vector3.Lerp(transform.position, targetPosition, smoothSpeed * Time.deltaTime);

        //Camera collision detection
        RaycastHit hit;
        if (Physics.Linecast(target.position, smoothedPosition, out hit, collisionLayers))
        {
            smoothedPosition = hit.point;
        }

        transform.position = smoothedPosition;
        transform.LookAt(target);
    }
}

Crucial addition:

  1. Added collisionLayers: This allows you to specify which layers the camera should collide with. Create a new layer (e.g., “Environment”) and assign it to your walls and other collidable objects. Assign this layer to the collisionLayers field in the Inspector.
  2. Physics.Linecast casts a ray from the target to the desired camera position. If it hits something on the collisionLayers, the hit variable contains information about the collision.
  3. If a collision occurs, smoothedPosition is set to the hit.point, effectively pulling the camera in front of the obstacle.

Practical Application: Experiment with different values for height, distance, smoothSpeed, and zoomSpeed to find the perfect feel for your game. Also, adjust the minDistance and maxDistance to allow for optimal zoom.

Common Mistake: Forgetting to assign the collisionLayers will render the collision detection useless. Double-check this setting!

This setup provides a solid foundation for a top-down camera. You can further enhance it by adding features like camera rotation, panning, or more sophisticated collision avoidance techniques. The key is understanding the core principles of camera control and adapting them to your specific game’s needs. Now go build something amazing!