ScreenToWorldPoint / Input.GetTouch(0) not working | place cube in 3d space

Hi, I’m trying to make an android game, and I need the player to place a cube on a 3d map.
Here is what I have :

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class Player : MonoBehaviour
{
    public Text myText;
    private Touch theTouch;

    private void Update()
    {
        if (Input.touchCount > 0)
        {
            theTouch = Input.GetTouch(0);

            if (theTouch.phase == TouchPhase.Ended)
            {
                Vector3 touchPos = Camera.main.ScreenToWorldPoint(new Vector3(theTouch.position.x, theTouch.position.y, 0.3f));

                transform.position = touchPos;

                myText.text = touchPos.ToString();
            }
        }
    }
}

And here is an example of 3d map (way flatter in my game) :

I saw on the ScreenToWorldPoint Unity page and on other pages that the third value of the Vector3 in ScreenToWorldPoint is like the camera distance from the map but I don’t really know how to get that and how it’s working. Can you help ?
Thanks :slight_smile:

Hello Tarezze,

The issue you’re facing likely arises from misunderstanding the use of ScreenToWorldPoint. The Z component in ScreenToWorldPoint is not the camera distance from the map but rather the distance into the screen, using the camera’s near clip plane as the reference point. Therefore, using a static value like 0.3 may not produce the results you expect.

In the case of a 3D game where you want to position objects on a terrain or a flat surface, raycasting is often a more appropriate choice.

Here’s a version of your script modified to use raycasting:

using UnityEngine;
using UnityEngine.UI;

public class Player : MonoBehaviour
{
    public Text myText;
    public LayerMask terrainLayer; // Assign the layer of your terrain in the Inspector

    private void Update()
    {
        if (Input.touchCount > 0)
        {
            Touch theTouch = Input.GetTouch(0);

            if (theTouch.phase == TouchPhase.Ended)
            {
                Ray ray = Camera.main.ScreenPointToRay(theTouch.position);
                RaycastHit hit;

                if (Physics.Raycast(ray, out hit, Mathf.Infinity, terrainLayer))
                {
                    Vector3 touchPos = hit.point;

                    transform.position = touchPos;
                    myText.text = touchPos.ToString();
                }
            }
        }
    }
}

In this script, when the player lifts their finger, a ray is cast from the camera through the touch point on the screen. If the ray hits the terrain, the position of the cube is set to the hit point. The terrainLayer variable should be set to the layer of your terrain to ensure the ray only interacts with the terrain and ignores other objects.

I hope this helps you with your problem, and best of luck with your game!