Limiting camera movement (2d map)

Hi,

I have made a map for my 3D scene and I have placed a camera in the sky looking down.
With below code (find here) I can pan the camera and zoom in and out.

My question is, how can I limit camera movement to the boundaries of map?

I’ve seen several threads on this subject but I can’t figure out it.

 using UnityEngine;
 using System.Collections;
 
 public class DragMap : MonoBehaviour {
     private float dist;
     private Vector3 v3OrgMouse;
     
     void Start () {
         dist = transform.position.y;  // Distance camera is above map
     }
     
     void Update () {
         if (Input.GetMouseButtonDown (0)) {
             v3OrgMouse = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
             v3OrgMouse = Camera.main.ScreenToWorldPoint (v3OrgMouse);
             v3OrgMouse.y = transform.position.y;
         } 
         else if (Input.GetMouseButton (0)) {
             var v3Pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
             v3Pos = Camera.main.ScreenToWorldPoint (v3Pos);
             v3Pos.y = transform.position.y;
             transform.position -= (v3Pos - v3OrgMouse);
         }
         
         if (Input.GetAxis("Mouse ScrollWheel") < 0 ) // Scroll back 
			orthographicSize+=10;

		 if (Input.GetAxis("Mouse ScrollWheel") > 0 ) // Scroll forward
			orthographicSize-=10;
     }
 }

Let me assume you were smart and setup your map so that it’s origin is at (0,0,0). For an Orthographic camera, the camera sees 1/2 of the screen height, so you can get how much it sees horizontally by:

 Camera.main.orthographicSize * Screen.width / Screen.height * 2.0;

This subtracted from the screen width and divided by 2.0 will give you the horizontal limits of the camera. The clamping values must be recalculated each time the camera is zoomed. Putting it together with your existing code, produces:

using UnityEngine;
using System.Collections;

public class DragMap : MonoBehaviour {
	private float dist;
	private Vector3 v3OrgMouse;

	public float mapWidth = 20.0f;
	public float zoomFactor = 0.4f;
	public float minZoom = 0.4f;

	private float maxZoom = 25.0f;
	private float minX, maxX;
	
	void Start () {
		dist = transform.position.y;  // Distance camera is above map
		CalcMinMax();
		maxZoom = Camera.main.orthographicSize * Screen.height / Screen.width * 2.0f;
	}
	
	void Update () {
		if (Input.GetMouseButtonDown (0)) {
			v3OrgMouse = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
			v3OrgMouse = Camera.main.ScreenToWorldPoint (v3OrgMouse);
			v3OrgMouse.y = transform.position.y;
		} 
		else if (Input.GetMouseButton (0)) {
			var v3Pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
			v3Pos = Camera.main.ScreenToWorldPoint (v3Pos);
			v3Pos.y = transform.position.y;
			transform.position -= (v3Pos - v3OrgMouse);
		}

		float sw = Input.GetAxis ("Mouse ScrollWheel");
		if (Mathf.Abs (sw) > 0.01f) {
			Camera.main.orthographicSize += sw * zoomFactor;
			Camera.main.orthographicSize = Mathf.Clamp (Camera.main.orthographicSize, minZoom, maxZoom);
			CalcMinMax();
		}
		Vector3 pos = transform.position;
		pos.x = Mathf.Clamp (pos.x, minX, maxX);
		transform.position = pos;
	}

	void CalcMinMax() {
		float height = Camera.main.orthographicSize * 2.0f;
		float width  = height * Screen.width / Screen.height;
		maxX = (mapWidth - width) / 2.0f;
		minX = -maxX;
	}
}

Note that I also added some limits to the zooming so that the use cannot zoom in to a negative number nor zoom out beyond the edges of the map.

Well, you’re calculating where the new cameraPosition is going to be. And I’m assuming you know the map dimensions. So, before you set the camera’s transform.position, limit those values to the map dimensions.

// Some public members should be set to your map's dimensions
public float minX;
public float maxX;
public float minZ;
public float maxZ;


// Your code
else if (Input.GetMouseButton (0))
{
    var v3Pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
    v3Pos = Camera.main.ScreenToWorldPoint (v3Pos);
    v3Pos.y = transform.position.y;

    // New limiting code
    // Calculate the new cameraPosition (the same a you did)
    Vector3 newCameraPosition = transform.position - (v3Pos - v3OrgMouse);
    // Now clamp the vector to our min/max's.
    newCameraPosition = new Vector3
    (
        Mathf.Clamp(newCamperaPosition.x, minX, maxX),
        newCameraPosition.y, // Could also min/max the y if you like.
        Mathf.Clamp(newCamperaPosition.z, minZ, maxZ)
    );

    transform.position = newCameraPosition;
}

I didn’t compile this code, but you should be able to get it working if there’s bugs. Let me know if there are any issues.

  • Eck