- Home /
ScreenToWorldPoint giving strange results
Hey everyone! I'm working on an element allignment system for my own GUISystem. Something simple, but good for now. Everything works fine except for the ScreenToWorldPoint function, which don't give the results that I was expecting. I don't think there's something wrong with my code. Here it is:
public static Vector3 allignElement (Transform element, Allignment allignment) {
Camera mainCamera = Camera.mainCamera;
float distance = mainCamera.nearClipPlane;
Vector3 GUIZoneElementScale = element.localScale;
if(allignment == Allignment.BottomCenter) {
Vector3 inScreenPos = new Vector3(Screen.width/2, 0, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if (allignment == Allignment.BottomLeft) {
Vector3 inScreenPos = new Vector3(0, 0, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if (allignment == Allignment.BottomRight) {
Vector3 inScreenPos = new Vector3(Screen.width, 0, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if (allignment == Allignment.MiddleCenter) {
Vector3 inScreenPos = new Vector3(Screen.width/2, Screen.height/2, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if (allignment == Allignment.MiddleLeft) {
Vector3 inScreenPos = new Vector3(0, Screen.height/2, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if (allignment == Allignment.MiddleRight) {
Vector3 inScreenPos = new Vector3(Screen.width, Screen.height/2, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if (allignment == Allignment.None) {
return element.transform.position;
} else if(allignment == Allignment.UpperCenter) {
Vector3 inScreenPos = new Vector3(Screen.width/2, Screen.height, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if(allignment == Allignment.UpperLeft) {
Vector3 inScreenPos = new Vector3(0, Screen.height, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
} else if(allignment == Allignment.UpperRight) {
Vector3 inScreenPos = new Vector3(Screen.width, Screen.height, distance);
return mainCamera.ScreenToWorldPoint( inScreenPos );
}
return Vector3.zero;
}
The problem is when I want an object to be in one of the corners. For instance, UpperLeft gives me this:

Any idea of why this can be happening?
Thanks from now!
I think of you are not using an ortho camera u have to use a ray from the camera to get the proper result
Answer by aldonaletto · Jul 09, 2012 at 05:28 PM
The nearPlane is too close to your camera - half object will be behind it, and not visible, and the other half will be after it, but still not visible because the back faces are culled out.
You should specify a bigger distance - 10, 20 etc. - to be able to see the objects. But there's a problem: the distance is measured from the camera position, thus the objects will actually be positioned in a spherical surface (radius = distance). If you really need then distributed over a flat surface perpendicular to the camera, you must create a logical plane and use plane.Raycast to find the distance from the ray origin, and ray.GetPoint to find the actual 3D hit point - like this:
... Vector3 GUIZoneElementScale = element.localScale; Vector3 fwd = mainCamera.transform.forward; Vector3 pos = mainCamera.transform.position + fwd * distance; // create a plane at distance, and facing the camera: Plane plane = new Plane(-fwd, pos); Ray ray; // ray to intersect the plane float dist = 0; // will contain the distance along the ray
if(allignment == Allignment.BottomCenter) { ray = mainCamera.ScreenPointToRay(new Vector3(Screen.width/2, 0, 0)); plane.Raycast(ray, out dist); // find the distance of the hit point return ray.GetPoint(dist); // return this point } else if (allignment == Allignment.BottomLeft) { ... Better yet, you could use ViewportPointToRay instead of ScreenPointToRay - the screen coordinates are expressed in the range 0..1, making it easier to specify the positions like left, middle and right (0, 0.5 and 1).
I though about this possibility but I tried to not use raycast... Seems like there's no other way. I'm aware about the ViewportPointToRay, I've already used it! Thanks for your help! Obrigado pela ajuda! :P
So... seems like the results were the same as the last ones... Even with raycast, the plane doesn't project himself in the borders. When I select an centered option, it works properly, but when I select an option that places the object in the borders, it doesn't work as it should.
Oops! I swapped the Plane arguments - they should be -fwd, pos
Edited the answer to fix this error, and in my tests it worked fine. Remember to set a reasonable value for distance, or the object may even not be visible at all.
Your answer
Follow this Question
Related Questions
What makes Camera.ScreenToWorldPoint return different results with same input? 0 Answers
Camera.main.ScreenToWorldPoint works within Unity editor, but not in builds 0 Answers
How to prevent continuous spinning while aiming at the screen's center? 0 Answers
An object who stay in the camera area 1 Answer
Screen to world point - parented camera 0 Answers