Best way to detect touch on a GameObject

I see there’re a lot of questions regarding touch detection since ever. As Unity is changing constantly, I want to know what is the best solution to detect touches on a 2D Game Object with the latest version of Unity (5.3).

Im making a Candy Crush clone, and I want to use that touches to move the icons (candies, gems, whatever you want).

5 Answers

5

I think the best way to achieve this would be using Raycasting, for this Specifically Physics2D.Raycast().

I don’t have access to Unity right now, but from memory you should try something like this:

using UnityEngine;
using System.Collections;

public class RaycastTest : MonoBehaviour {

    Vector3 touchPosWorld;

    //Change me to change the touch phase used.
    TouchPhase touchPhase = TouchPhase.Ended;

    void Update() {
        //We check if we have more than one touch happening.
        //We also check if the first touches phase is Ended (that the finger was lifted)
        if (Input.touchCount > 0 && Input.GetTouch(0).phase == touchPhase) {
            //We transform the touch position into word space from screen space and store it.
            touchPosWorld = Camera.main.ScreenToWorldPoint(Input.GetTouch(0).position);

            Vector2 touchPosWorld2D = new Vector2(touchPosWorld.x, touchPosWorld.y);

            //We now raycast with this information. If we have hit something we can process it.
            RaycastHit2D hitInformation = Physics2D.Raycast(touchPosWorld2D, Camera.main.transform.forward);

            if (hitInformation.collider != null) {
                //We should have hit something with a 2D Physics collider!
                GameObject touchedObject = hitInformation.transform.gameObject;
                //touchedObject should be the object someone touched.
                Debug.Log("Touched " + touchedObject.transform.name);
            }
        }
    }
}

Again please check this works, as i cannot at the current time of writing. You can change touchPhase to change the TouchPhase used to detect a touch, link to the doc for this Enum is here. Check the documentation for Input.GetTouch() for more examples and information on how to get and use Touches.

You probably want to modify this to check if a touch begins and ends on the same object, but this is a good starting point for basic functionality.

Hope this helps!

Note: This can be slightly modified to suit for 3D gameobjects. If there are easier ways to achieve this please comment and correct me.

Tried that code and doesn't work :( Nevertheless, I want to know the best way, it doesn't matter if there's code, a link to a tutorial, or just "use raycast and 2d colliders". Right now I can do it using the Mouse events, as they're mapped to touch. But I don't know if it's the best.

Sorry, made myself unclear by saying "finished programming". I said that I meant by that in the reply for phxvyper. thanks and sorry again for not making myself clear. thanks for the article thing, that helped me a lot. thanks again and have a nice day! :)

better and easy way, just add box collider and a script with this event to your game object:

OnMouseUpAsButton() { }

Yeah , that's works for me . Sometimes I forget to take a step back and think simpler :) . Thanks

While this is the best answer, the collider should be the one that fits your solution.

Maybe Try this:

if (Input.touchCount == 1 && Input.GetTouch(0).phase == touchPhase) {
        Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
		RaycastHit hit;

		Debug.DrawRay(ray.origin, ray.direction * 100, Color.yellow, 100f);

		if(Physics.Raycast(ray, out hit))
		{
			Debug.Log(hit.transform.name);
			if (hit.collider != null) {
				
				GameObject touchedObject = hit.transform.gameObject;
				
				Debug.Log("Touched " + touchedObject.transform.name);
			}
		}
 }

touchPhase is set to TouchPhase.Began

A combination from @rob5300 post and 26 - How to Detect Mouse Click or Touch on a GameObject - YouTube

#if !UNITY_EDITOR
if( Input.touchCount>0 )
{
foreach( Touch t in Input.touches )
{
Debug.LogError("current touch {Input.touches}"); Debug.LogError(“touch count is {Input.touchCount}”);
Vector3 touchPos = t.position;
if( t.phase==TouchPhase.Began )
{
Ray ray = Camera.main.ScreenPointToRay( touchPos );
RaycastHit2D hit = Physics2D.Raycast( ray.origin , ray.direction );
if( hit.collider!=null && hit.transform==transform )
{
Debug.Log($“Hit: {hit.transform.name}”);
myOnMouseDown();
break;
}
}
}
}
#endif

I am using unity visual scripting, and trying to figure out how to translate the hit.transform == "transform" part into visual script, I put quotes on the part in question. EDIT: I actually thought I could do a call to a literal transform (none) but really I just had to check if the hit.transform wasn't null. So now it works, thanks for the nice simple architecture for this.

Adding more colliders certainly won't make the engine perform faster unless you somehow had a situation where your raycasts (without filtering) make for over 50% of the performance hit in the game. The physics engines in Unity are pretty damn mature and optimized so don't spend time thinking about complex ways to optimize things before you know you have a performance problem.

will the debug for raycast touch position response if i use mouse to click on the object during the game view in unity? because I’m trying to test out whether the raycast by touch position is working or not.

@frhilyana118 questions should be on comments, not answers