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!

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).