Keep Top Down 2D camera in bounds of background sprite
Hi.
I'm trying to make a 2D top down camera for my game. I'm a beginner but I managed to solve it for 1 background sprite. My soloution was not a general soloution though and it only works for that particular sprite. I would kindly accept any help of how I would be able to calculate the bounds of any sprite and use it in my script.
This is what I've done so far:
using UnityEngine;
using System.Collections;
public class CameraBounds : MonoBehaviour
{
//I write the value of the bound in the inspector
public float rightBound;
public float leftBound;
public float topBound;
public float bottomBound;
private Vector3 pos;
private Transform target;
// Use this for initialization
void Start ()
{
target = GameObject.FindWithTag("Player").transform;
}
// Update is called once per frame
void Update ()
{
Debug.Log(pos);
transform.position = pos;
if(pos.x != rightBound || pos.x != leftBound || pos.y != topBound || pos.y != bottomBound)
{
pos = new Vector3(target.position.x, target.position.y, transform.position.z);
}
//Right
if(pos.x >= rightBound)
{
pos.x = rightBound;
}
//Left
if(pos.x <= leftBound)
{
pos.x = leftBound;
}
//Top
if(pos.y >= topBound)
{
pos.y = topBound;
}
//Bottom
if(pos.y <= bottomBound)
{
pos.y = bottomBound;
}
}
}
For clarification: Do you want the camera to be bounded by the boundaries of the background sprite, so that you can't see beyond its edges?
Without knowing your game mechanic it is difficult to tell, but it seems to me that there are issues with the 'if' statement on line 22. And you can simplify this code some. I think you want something more like:
void Update() {
var pos = new Vector3(target.position.x, target.position.y, transform.position.z);
pos.x = $$anonymous$$athf.Clamp(pos.x, leftBound, rightBound);
pos.y = $$anonymous$$athf.Clamp(pos.y, bottomBound, topBound);
transform.position = pos;
}
If you wanted to make this general code you would need to use the bounds of the sprite and the orthographic size of the camera. You can get the bounds using the SpriteRenderer.sprite.bounds. The Orthographic size is 1/2 the vertical size seen by the camera. You can get the horizontal size by using the aspect ration of the camera.
Joshpsawyer: Correct
Robertbu: Thank you for introducing me to mathf.clamp. The code you provided worked really well and I replaced it with my former code.
I have also got hold of the sprites bounds and vertical / horizontal size but I do not know how to use them properly. Can you explain how I should use the values to make it general? :)
Thanks in advance.
Answer by Paikz · Apr 14, 2014 at 01:48 PM
Solved it after the answers I've been given + some googling.
Here's the script I came up with:
private float rightBound;
private float leftBound;
private float topBound;
private float bottomBound;
private Vector3 pos;
private Transform target;
private SpriteRenderer spriteBounds;
// Use this for initialization
void Start ()
{
float vertExtent = Camera.main.camera.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height;
spriteBounds = GameObject.Find("1 - Background").GetComponentInChildren<SpriteRenderer>();
target = GameObject.FindWithTag("Player").transform;
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
}
// Update is called once per frame
void Update ()
{
//Debug.Log();
var pos = new Vector3(target.position.x, target.position.y, transform.position.z);
pos.x = Mathf.Clamp(pos.x, leftBound, rightBound);
pos.y = Mathf.Clamp(pos.y, bottomBound, topBound);
transform.position = pos;
}
void OnLevelWasLoaded()
{
Start();
}
Helpfull link: http://answers.unity3d.com/questions/501893/calculating-2d-camera-bounds.html
Thanks for the help guys (Joshpsawyer & robertbu)! I'm glad you took the time to help me out. :)
No problem! You should mark your answer as accepted so that the question won't remain active.
Sorry to bother, but there's a tiny error in this code, line 13:
float vertExtent = Camera.main.**camera.**orthographicSize;
This camera. does not compile; I'm just posting this here. Good day,
Lewinow
Everything from more than a few years ago will have that problem. Now you have to use GetComponent<Camera>()
. But back then dot-camera (as written above) was a shortcut. You have the same problem with rigidbodies, renderers ... all those had a shortcut, which is now gone.
Answer by MorphVGX · Aug 03, 2016 at 09:51 PM
This is what worked for me to get the limits for the camera position:
float camExtentV = _cam.orthographicSize;
float camExtentH = (camExtentV * Screen.width) / Screen.height;
Bounds levelBounds = LevelBoundsSpriteRenderer.bounds;
float leftBound = levelBounds.min.x + camExtentH;
float rightBound = levelBounds.max.x - camExtentH;
float bottomBound = levelBounds.min.y + camExtentV;
float topBound = levelBounds.max.y - camExtentV;
Answer by Simon-Larsen · Jul 19, 2021 at 12:01 AM
I needed something like this, but a tiny bit different. My camera had to support zooming, so initialization in Start
was not sufficient. Adjusted your sample code to support a camera with dynamic bounds and added the possibility for padding.
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class BoundedCamera : MonoBehaviour
{
public SpriteRenderer spriteBounds;
// Pad the bounded area to 'paddingRatio'. Such that 1 means the camera can fully reach the bounds and 0.95 provides a 5% padding on all ends
public float paddingRatio = 1f;
private new Camera camera;
void Start()
{
camera = GetComponent<Camera>();
}
void LateUpdate()
{
float verticalExtent = camera.orthographicSize;
float horizontalExtent = verticalExtent * Screen.width / Screen.height;
float spriteWidth = spriteBounds.sprite.bounds.size.x / 2.0f;
float spriteHeight = spriteBounds.sprite.bounds.size.y / 2.0f;
var leftBound = spriteBounds.transform.position.x + paddingRatio * (horizontalExtent - spriteWidth);
var rightBound = spriteBounds.transform.position.x + paddingRatio * (spriteWidth - horizontalExtent);
var bottomBound = spriteBounds.transform.position.y + paddingRatio * (verticalExtent - spriteHeight);
var topBound = spriteBounds.transform.position.y + paddingRatio * (spriteHeight - verticalExtent);
var pos = new Vector3(transform.position.x, transform.position.y, transform.position.z);
pos.x = Mathf.Clamp(pos.x, leftBound, rightBound);
pos.y = Mathf.Clamp(pos.y, bottomBound, topBound);
transform.position = pos;
}
}
Your answer
Follow this Question
Related Questions
Background in 2D game: sprite or image? 0 Answers
Scrolling background wall collision problem 0 Answers
How to draw background image on camera without MVP Matrix 0 Answers
[Beginner Question] Loading, Destroying and Replacing UI Background Sprites (2D) 0 Answers
Unity 2D camera Bounds for player 0 Answers