- Home /
 
Problem with ScreenToWorldPoint and touches (C#)
I am trying to instantiate an object at the point where the the player touches the screen. Here is my code so far:
 public class CreateObject : MonoBehaviour
 {
     public GameObject createdObject;
     
     void Update ()
     {
         foreach (Touch touch in Input.touches)
         {
             if (touch.phase == TouchPhase.Began)
             {
                 Vector3 vec = Camera.main.ScreenToWorldPoint(touch.position);
                 vec.z = 0;
                 Instantiate(createdObject, vec, Quaternion.identity);
             }
         }
     }
 }
 
               The problem is that vec always returns as 0,0,0 (or rather 0, 0, -10, but I changed the z value to 0). What am I doing wrong? Just FYI, I have my camera located at 0, 0, -10 and facing 0, 0, 0 in world space. Not sure if that matters or not. Thanks!
Answer by aldonaletto · Dec 27, 2011 at 12:42 AM
ScreenToWorldPoint must receive a Vector3 where x and y are the screen coordinates, and z is the distance from the camera. Since you're passing a Vector2, the compiler promotes it to Vector3 setting the z coordinate to 0, what will always return the camera position, no matter what x and y are.
If must copy touch.position to a Vector3 variable and set its z component to the distance you want:
    Vector3 tch = touch.position;
    tch.z = 15; // define distance from the camera
    Vector3 vec = Camera.main.ScreenToWorldPoint(tch);
    Instantiate(....);
 Unfortunately, this will create all objects at a fixed distance from the camera - or at the surface of a sphere with radius 15, in this case.
               If you want to create the objects in a plane, you should use ScreenPointToRay instead: create the base plane, create the ray, use plane.Raycast to find the distance, and ray.GetPoint(distance) to find the point... a piece of cake, for sure! But don't panic, the whole thing is easier than it may look:
public class CreateObject : MonoBehaviour {
 public GameObject createdObject;
 // create a plane in xy, at z = 5
 Plane basePlane = new Plane(-Vector3.forward, new Vector3(0, 0, 5));
 void Update (){
    foreach (Touch touch in Input.touches){
      if (touch.phase == TouchPhase.Began){ 
        // no need to set z, because ScreenPointToRay ignores it
        Ray ray = Camera.main.ScreenPointToRay(touch.position);
        float distance;
        if (basePlane.Raycast(ray, distance)){
          Vector3 vec = ray.GetPoint(distance); // get the plane point hit
          Instantiate(createdObject, vec, Quaternion.identity);
        }
      }
    }
 }
 
               }
Answer by Rod-Green · Dec 27, 2011 at 01:03 AM
It's an issue with vec2 to vec3 conversion:
 public class CreateObject : MonoBehaviour
 {
     public GameObject createdObject;
 
     void Update ()
     {
         foreach (Touch touch in Input.touches)
         {
             
             if (touch.phase == TouchPhase.Began)
             {
                 Vector3 vec = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, Camera.main.nearClipPlane + 5.0f));
                 Vector3 oldVec = Camera.main.ScreenToWorldPoint(touch.position);
                 Debug.Log (oldVec + " vs " + vec);
                 //vec.z = 0;
                 Instantiate (createdObject, vec, Quaternion.identity);
             }
         }
     }
 }
 
              Your answer
 
             Follow this Question
Related Questions
Unity 2D Rouge-Like game tutorial help 0 Answers
Distribute terrain in zones 3 Answers
Multiple Cars not working 1 Answer
Objects seemingly not being instantiated after touch. 1 Answer
Trying To Find Mouse Position On Tap 1 Answer