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!

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);
           }
         }
       }
    }
}

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);
			}
		}
	}
}