0
\$\begingroup\$

I have instantiated objects (that have collider2D attached) in a grid of 9x13. Now I want to detect a touch on each object individually. I am confused about how to do it. Either write script separately on prefab or do it in my gameController script? Also what is the method to do it?

Here is my code for instantiating:

    public GameObject bubble;
    int row;
    int col;
    float x;
    float y;


    void Start () 
    {
        x = -2.4f;
        y = 2.95f;
        row = 13;
        col = 9;

        Vector2 position = new Vector2(x, y);

        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                Instantiate(bubble, position, Quaternion.identity);
                position.x += 0.6f;
            }
            position.x = x;
            position.y -= 0.6f;
        }
    }

\$\endgroup\$
  • \$\begingroup\$ By "detect touch" you mean detect when a pointer (mouse / finger / stylus) clicks/presses over the object on screen? \$\endgroup\$ – DMGregory May 16 at 11:27
  • \$\begingroup\$ button press or finger touch on the object \$\endgroup\$ – thirteen4054 May 16 at 11:29
0
\$\begingroup\$

The simplest way is to give your prefab a suitable collider, and attach a script to the prefab that looks a bit like this:

public class TouchDetector : MonoBehaviour {

    // Called when a collider attached to this game object is pressed.
    void OnMouseDown() {
        // Put the actions you want to perform to respond to the touch here.
        Debug.LogFormat("Object {0} got touched!", gameObject.name);
    }
}

When you build, Unity looks for any MonoBehaviour scripts that have OnMouseDown or other mouse-related messages. If it finds them, then it automatically fires a ray into your scene every frame to see what collider it hits first, and then sends the corresponding up/down/enter/exit messages.

This also works for a single finger touch or stylus. I don't know if it handles multitouch in a useful way.

The downside is that this is a very generic solution, so it might be more heavyweight than you need (maybe you don't care about enter/exit/up messages at all, or only some of your objects need the pointer interaction, or you have gobs of objects and don't want to put a receiver script on every one of them...)

So, in many cases you can make this more efficient by firing the ray yourself, only when it's appropriate for your game rules.

Here we could have a single script that fires a ray for each touch and detects what it hits - without needing a receiving script on each prefab instance:

public class TouchManager : MonoBehaviour {

    public LayerMask touchableLayers;

    void Update() {
        var camera = Camera.main;

        int count = Input.touchCount;
        for(int i = 0; i < count; i++) {
            var touch = Input.GetTouch(i);

            var ray = camera.ScreenPointToRay(touch.position);

            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, Mathf.infinity, touchableLayers)) {
                // Pur the actions you want to perform to respond to the touch here.
                Debug.LogFormat("Object {0} got touched!", hit.collider.gameObject.name);
            }
        }   
    }    
}
\$\endgroup\$
  • \$\begingroup\$ yes I did almost something like this it checks a if it is on a sprite and then checks the tag. but this is also an answer to my question. \$\endgroup\$ – thirteen4054 May 16 at 13:45
0
\$\begingroup\$

I've done this in my game controller script (but you don't have to). Whichever makes more sense to you, I think.

One method you can use is OnTriggerEnter.

Your could use code that goes something like the below. It will let you tag all the objects with one tag but you can do something with each individually -- if you want to do the same thing with each object but just have it happen only when that specific one is touched.

void OnTriggerEnter(Collider collider) {

    if (collider.gameObject.CompareTag("insert_tag_of_gameobject") {

do whatever you'd like to do with the object you've collided with }

If you only want to do something that is specific to a single object when you hit it then maybe try using something like this:

//this code says that when you collide with the object that the collider is attached to, find that object (then insert code that does whatever you want to do with the object) void OnTriggerEnter(Collider collider) {

    objectName = GameObject.Find("object_name");

do whatever you'd like to do with the object }

\$\endgroup\$
  • \$\begingroup\$ do i need to store all the instantiated objects in a list to do this? \$\endgroup\$ – thirteen4054 May 16 at 11:28
  • \$\begingroup\$ No, or at least I didn't need to do that. I just made them prefabs and named/tagged them as needed. \$\endgroup\$ – Pete Bloom May 16 at 11:37
  • \$\begingroup\$ void OnTriggerEnter2D(Collider2D collider) { if (collider.gameObject.CompareTag("bubble")) { Debug.Log("detected"); } } \$\endgroup\$ – thirteen4054 May 16 at 11:45
  • \$\begingroup\$ I used this in my gameController and added a tag "bubble" to my prefab but when I touch any bubble its not giving output \$\endgroup\$ – thirteen4054 May 16 at 11:45
  • \$\begingroup\$ Have you checked 'is trigger' on the game object (in the Inspector panel)? \$\endgroup\$ – Pete Bloom May 16 at 11:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.