- Home /
map boundaries for perspective camera
Hi,
I'm building a 2.5D game, where the perspective camera is looking to the side of the level and the characters can only move on the X and Y direction. I'm having a very hard time trying to get the camera not to leave the boundries of the map. The camera is free to move over the X and Y axis and can zoom in and out. What i managed to do is;
Vector3 downRightEdgeScreen = Camera.main.WorldToScreenPoint(downRightEdge);
Debug.Log (downRightEdgeScreen);
if(downRightEdgeScreen.x < 0){
Vector3 downRightEdgeScreenFixed = Camera.main.ScreenToWorldPoint(new Vector3(0f, downRightEdgeScreen.y, downRightEdgeScreen.z));
float dis = downRightEdgeScreen.x-downRightEdgeScreenFixed.x;
Debug.Log("Fixed: "+dis);
}
Where then dis gives the units i need to move that vector to be inside the screen again. Now how can i convert this dis back to the camera and move the camera to make sure that that vector is inside the screen? So basically what i want to know is, how can i convert units on the x axis at a certain distance to the units the camera has to move cover that distance. Maybe my whole concept is wrong and there are easier ways of doing this, i would be very interested to learn.
Many thanks
Hi SaraCecilia thanks for your answer! Clamp would work if it was not for the scaling and the perspective camera.. This makes it hard since i don't have the formule to change the bounds based on the distance of the camera.
Answer by Erik-Sombroek · Jul 22, 2015 at 04:15 PM
Hi,
In the end i managed to solve it using a virtual Plane infront of the camera that i raycast onto to get the position of where the camera should be to not have the map out of bounds.
Attached image illustrates the concept:
A: We first translate the map bound A to the screen space
B: We thenpush point A to the border of the camera (at the Z depth of point A)
C: Now we know how much we have to push this vector on the X-axis at given distance so that the Camera is in bounds again.
D: Here we translate the center of the camera to the world coordinates at distance Z (distance of the A vector).
E: We then offset point D with the distance we found at C
F: Now we raycast from point E with a negative direction of camera.forward on to a plane that is placed at the position of the camera with normal facing to camera.forward
Now we know exactly where to place the camera to make sure the camera doesn't go out of the map bounds.
Here is the code, i tried to comment as much as possible:
Vector3 topRightEdgeScreen = Camera.main.WorldToScreenPoint(topRightEdge);
Vector3 downLeftEdgeScreen = Camera.main.WorldToScreenPoint(downLeftEdge);
Debug.Log(downLeftEdgeScreen+" "+Screen.height);
// Is the camera out of the map bounds?
if(topRightEdgeScreen.x < Screen.width || topRightEdgeScreen.y < Screen.height || downLeftEdgeScreen.x > 0 || downLeftEdgeScreen.y>0){
//smack a big plane at the camera position that covers more than the screen is showing
cameraPositionFixPlane = new Plane(Vector3.forward*10, Camera.main.transform.position);
//move the top right edge back so its inside the screen again
Vector3 topRightEdgeScreenFixed = Camera.main.ScreenToWorldPoint(new Vector3(Mathf.Max(Screen.width, topRightEdgeScreen.x), Mathf.Max(Screen.height,topRightEdgeScreen.y), topRightEdgeScreen.z));
//now we know the offset the camera should move at distance z to fix the top right edge
Vector3 topRightOffsetAtDistance = topRightEdgeScreenFixed-topRightEdge;
//this time for the down left edge
Vector3 downLeftEdgeScreenFixed = Camera.main.ScreenToWorldPoint(new Vector3(Mathf.Min(0, downLeftEdgeScreen.x), Mathf.Min(0, downLeftEdgeScreen.y), downLeftEdgeScreen.z));
//now we know the offset the camera should move at distance z to fix the down left edge
Vector3 downLeftOffsetAtDistance = downLeftEdgeScreenFixed-downLeftEdge;
Debug.Log ("offset: "+downLeftOffsetAtDistance);
//where is the center of the screen translated at given distance
Vector3 cameraCenterAtDistance = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width/2.0f, Screen.height/2.0f, topRightEdge.z));
//now lets offset the center of the screen with the offset we found
Vector3 cameraCenterAtDistanceFixed = new Vector3(cameraCenterAtDistance.x-topRightOffsetAtDistance.x-downLeftOffsetAtDistance.x, cameraCenterAtDistance.y-topRightOffsetAtDistance.y-downLeftOffsetAtDistance.y, cameraCenterAtDistance.z);
//here we generate a ray at the camera center at distance pointing back to the camera
Ray rayFromFixedDistanceToCameraPlane = new Ray(cameraCenterAtDistanceFixed, -Camera.main.transform.forward);
//this is where the magic happens, lets raycast back to the plane i smacked infront of the camera
float d;
cameraPositionFixPlane.Raycast(rayFromFixedDistanceToCameraPlane, out d);
//where did the raycast hit the camera plane?
Vector3 planeHitPoint = rayFromFixedDistanceToCameraPlane.GetPoint(d);
//position camera at the hitpoint we found
Camera.main.transform.position = new Vector3(planeHitPoint.x, planeHitPoint.y, Camera.main.transform.position.z);
}
Hope this will help someone!
Best,
Erik Sombroek