Get world position of mouse click with Z equals to 0

Here are a lot of good methods in Camera, which can be used to translate mouse click position into world coordinates.

But what if i want to get world position of my click-point, which is layed on XY world plane? My camera can be in any position (X,Y and Z can be changed), but always looking perpendicular to XY world plane.

As i remember from my CG course, it’s a matter of solving two equations.
I mean, if i can construct the ray from click position towards XY plane (like with ScreenPointToRay method) and i know, that i need the point on this ray with Z=0, can i somehow get the rest of the coordinates (X and Y) ?
I have searched Ray methods but without success. So, my questions are:

  • Am i wrong about simplicity of this task in general?
  • If i’m right, is there a simple way (i mean just simple math, without raycasting and things) to get such point in Unity?
  • If there is no simple way of doing this, do i have only one option to solve my problem - casting rays with Physics.Raycast?

Thanks in advance.

The easy and relatively efficient method to solve this problem is to use Unity’s mathematical Plane class. From memory (and assuming you’ve constructed ‘ray’ the code would be:

 var plane = new Plane(Vector3.forward, Vector3.zero);
 var dist : float;
 plane.Raycast(ray, dist);
 var pos = ray.GetPoint(dist);

Note I’m assuming based on your question that the ray cannot miss the plane. If the ray can miss the plane, you need to check the return value from the ‘plane.Raycast()’.

Also note if for some reason you want to do a Raycast against a collider (less efficient that Unity’s mathematical Plane), you can do a Collider.Raycast(). A Physics.Raycast() cast against al the colliders in the scene (or all the ones on the layer(s) you specify with the layer mask). Collider.Raycast() casts against a single collider.

Finally there is a library of 3D math functions on the Unity Wiki:

http://wiki.unity3d.com/index.php/3d_Math_functions

The LinePlaneIntersection() function in this script does what you are asking for.

Edit: one final addition. You can accomplish the same thing with Camera.ScreenToWorldPoint() if the camera rotation is (0,0,0). When you call this function, make sure the ‘z’ value is distance the camera is away from z = 0; Example code:

 var pos = Input.mousePosition;
 pos.z = -Camera.main.transform.position.z;
 pos = Camera.main.ScreenToWorldPoint(pos);