Collision with sides of screen?

I’m trying to make a very simple test - a ball that bounces around, off the edges of the screen. I get using BoxCollider2D’s, but would I use code to create BoxCollider2D’s that are located just outside the screen?? Or is there a more efficient way to do this kind of thing? I imagine this is a common thing to need in a game… the trick is obviously needing the collision areas to move based on the resolution/aspect ratio.

Well, it’s not that common of a need, usually people just eyeball it I think, but if you want to adjust for aspect ratio, then here’s some code I just wrote up that does the trick:

	public float colDepth = 4f;
	public float zPosition = 0f;
	private Vector2 screenSize;
	private Transform topCollider;
	private Transform bottomCollider;
	private Transform leftCollider;
	private Transform rightCollider;
	private Vector3 cameraPos;
	// Use this for initialization
	void Start () {
	//Generate our empty objects
		topCollider = new GameObject().transform;
		bottomCollider = new GameObject().transform;
		rightCollider = new GameObject().transform;
		leftCollider = new GameObject().transform;

	//Name our objects	
		topCollider.name = "TopCollider";
		bottomCollider.name = "BottomCollider";
		rightCollider.name = "RightCollider";
		leftCollider.name = "LeftCollider";
		
	//Add the colliders
		topCollider.gameObject.AddComponent<BoxCollider2D>();
		bottomCollider.gameObject.AddComponent<BoxCollider2D>();
		rightCollider.gameObject.AddComponent<BoxCollider2D>();
		leftCollider.gameObject.AddComponent<BoxCollider2D>();
		
	//Make them the child of whatever object this script is on, preferably on the Camera so the objects move with the camera without extra scripting
		topCollider.parent = transform;
		bottomCollider.parent = transform;
		rightCollider.parent = transform;
		leftCollider.parent = transform;
			
	//Generate world space point information for position and scale calculations
		cameraPos = Camera.main.transform.position;
		screenSize.x = Vector2.Distance (Camera.main.ScreenToWorldPoint(new Vector2(0,0)),Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, 0))) * 0.5f;
		screenSize.y = Vector2.Distance (Camera.main.ScreenToWorldPoint(new Vector2(0,0)),Camera.main.ScreenToWorldPoint(new Vector2(0, Screen.height))) * 0.5f;
		
	//Change our scale and positions to match the edges of the screen...	
		rightCollider.localScale = new Vector3(colDepth, screenSize.y * 2, colDepth);
		rightCollider.position = new Vector3(cameraPos.x + screenSize.x + (rightCollider.localScale.x * 0.5f), cameraPos.y, zPosition);
		leftCollider.localScale = new Vector3(colDepth, screenSize.y * 2, colDepth);
		leftCollider.position = new Vector3(cameraPos.x - screenSize.x - (leftCollider.localScale.x * 0.5f), cameraPos.y, zPosition);
		topCollider.localScale = new Vector3(screenSize.x * 2, colDepth, colDepth);
		topCollider.position = new Vector3(cameraPos.x, cameraPos.y + screenSize.y + (topCollider.localScale.y * 0.5f), zPosition);
		bottomCollider.localScale = new Vector3(screenSize.x * 2, colDepth, colDepth);
		bottomCollider.position = new Vector3(cameraPos.x, cameraPos.y - screenSize.y - (bottomCollider.localScale.y * 0.5f), zPosition);
	}

This script can be used for 3D colliders as well, just remove the “2D” part on those four BoxCollider component lines.

8 Likes

Wow thanks so much man!! Much appreciated!

I actually took some time tonight to learn more about Dictionaries since this was a good enough time as any… Managed to shorten/simplify the code a fair bit! Dictionaries are pretty neat.

	public float colThickness = 4f;
	public float zPosition = 0f;
	private Vector2 screenSize;

	void Start ()
	{//Create a Dictionary to contain all our Objects/Transforms
		System.Collections.Generic.Dictionary<string,Transform> colliders = new System.Collections.Generic.Dictionary<string,Transform>();
	//Create our GameObjects and add their Transform components to the Dictionary we created above
		colliders.Add("Top",new GameObject().transform);
		colliders.Add("Bottom",new GameObject().transform);
		colliders.Add("Right",new GameObject().transform);
		colliders.Add("Left",new GameObject().transform);
	//Generate world space point information for position and scale calculations
		Vector3 cameraPos = Camera.main.transform.position;
		screenSize.x = Vector2.Distance (Camera.main.ScreenToWorldPoint(new Vector2(0,0)),Camera.main.ScreenToWorldPoint(new Vector2(Screen.width, 0))) * 0.5f; //Grab the world-space position values of the start and end positions of the screen, then calculate the distance between them and store it as half, since we only need half that value for distance away from the camera to the edge
		screenSize.y = Vector2.Distance (Camera.main.ScreenToWorldPoint(new Vector2(0,0)),Camera.main.ScreenToWorldPoint(new Vector2(0, Screen.height))) * 0.5f;
	//For each Transform/Object in our Dictionary
		foreach(KeyValuePair<string,Transform> valPair in colliders)
		{
			valPair.Value.gameObject.AddComponent<BoxCollider2D>(); //Add our colliders. Remove the "2D", if you would like 3D colliders.
			valPair.Value.name = valPair.Key + "Collider"; //Set the object's name to it's "Key" name, and take on "Collider".  i.e: TopCollider
			valPair.Value.parent = transform; //Make the object a child of whatever object this script is on (preferably the camera)

			if(valPair.Key == "Left" || valPair.Key == "Right") //Scale the object to the width and height of the screen, using the world-space values calculated earlier
				valPair.Value.localScale = new Vector3(colThickness, screenSize.y * 2, colThickness);
			else
				valPair.Value.localScale = new Vector3(screenSize.x * 2, colThickness, colThickness);
		} 	
	//Change positions to align perfectly with outter-edge of screen, adding the world-space values of the screen we generated earlier, and adding/subtracting them with the current camera position, as well as add/subtracting half out objects size so it's not just half way off-screen
		colliders["Right"].position = new Vector3(cameraPos.x + screenSize.x + (colliders["Right"].localScale.x * 0.5f), cameraPos.y, zPosition);
		colliders["Left"].position = new Vector3(cameraPos.x - screenSize.x - (colliders["Left"].localScale.x * 0.5f), cameraPos.y, zPosition);
		colliders["Top"].position = new Vector3(cameraPos.x, cameraPos.y + screenSize.y + (colliders["Top"].localScale.y * 0.5f), zPosition);
		colliders["Bottom"].position = new Vector3(cameraPos.x, cameraPos.y - screenSize.y - (colliders["Bottom"].localScale.y * 0.5f), zPosition);
	}
8 Likes

Many thank

for orthographic camera i’ve used this to make edge colliders:

2 Likes

Great script. Thanks man :slight_smile:

love it!

This function will generate colliders on the sides of the screen:

    void GenerateCollidersAcrossScreen()
    {
        Vector2 lDCorner = camera.ViewportToWorldPoint(new Vector3(0, 0f, camera.nearClipPlane));
        Vector2 rUCorner = camera.ViewportToWorldPoint(new Vector3(1f, 1f, camera.nearClipPlane));
        Vector2[] colliderpoints;

        EdgeCollider2D upperEdge = new GameObject("upperEdge").AddComponent<EdgeCollider2D>();
        colliderpoints = upperEdge.points;
        colliderpoints[0] = new Vector2(lDCorner.x, rUCorner.y);
        colliderpoints[1] = new Vector2(rUCorner.x, rUCorner.y);
        upperEdge.points = colliderpoints;

        EdgeCollider2D lowerEdge = new GameObject("lowerEdge").AddComponent<EdgeCollider2D>();
        colliderpoints = lowerEdge.points;
        colliderpoints[0] = new Vector2(lDCorner.x, lDCorner.y);
        colliderpoints[1] = new Vector2(rUCorner.x, lDCorner.y);
        lowerEdge.points = colliderpoints;

        EdgeCollider2D leftEdge = new GameObject("leftEdge").AddComponent<EdgeCollider2D>();
        colliderpoints = leftEdge.points;
        colliderpoints[0] = new Vector2(lDCorner.x, lDCorner.y);
        colliderpoints[1] = new Vector2(lDCorner.x, rUCorner.y);
        leftEdge.points = colliderpoints;

        EdgeCollider2D rightEdge = new GameObject("rightEdge").AddComponent<EdgeCollider2D>();

        colliderpoints = rightEdge.points;
        colliderpoints[0] = new Vector2(rUCorner.x, rUCorner.y);
        colliderpoints[1] = new Vector2(rUCorner.x, lDCorner.y);
        rightEdge.points = colliderpoints;
    }
2 Likes

Dude, that saved my day. Thank you so much.

Worked for me! Thank you!

Hi there, I got errors there as I wanted to do this, I am really a beginner, a dumb one, so I’ve trouble figuring it out. There is same error for four lines:
A namespace cannot directly contain members such as fields or methods

this goes for Line 5 column 14, Line 6 column 14, Line 7 column 17, Line 9 column 10.

I really don’t want my player to go out of bounds here and I want it to be able to adapt to aspect ratio.