0

I have two game objects in my scene and I assign this script to them both. When I click on any of them the code inside the If statement related to each one gets executed twice, if I disable one of them, it gets executed once as it should.

void Update () 
{
    if (Input.GetMouseButtonDown(0))
    {
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out hit))
        {
            if (hit.transform.name == "Object A")
            {
                Debug.Log("Object A Clicked");    // log twice
            }

            if (hit.transform.name == "Object B")
            {
                Debug.Log("Object B Clicked");   // log twice
            }
        }
    }
}

The question is, why does the code gets executed twice with for a single click?!

Olivier Moindrot
  • 27,908
  • 11
  • 92
  • 91
Abdou023
  • 1,654
  • 2
  • 24
  • 45

3 Answers3

1

The question is, why does the code gets executed twice with for a single click?!

Because each Update () function from every script is called every frame. Input.GetMouseButtonDown(0) will be true in each frame in every script that has it in the Update function.

If you want it to detect once, you two options:

1.Attach the script to one GameObject only. Usually, an empty GameObject. It should detect any Gamebject with a collider once when clicked.

2.Use the IPointerDownHandler and its OnPointerDown function. You can attach this to every GameObject you want to detect click on. Check #6 from here for 2d/sprites. For 3D Objects, check #6.

Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
0

This gets executed twice because when you hit a target with a click, it does this

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

That line of code, will give you the object, and since you have the script in 2 objects, it will run 2 times the exactly same thing. Both objects will recive the same ray.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
0

It was logging twice because, both objects sends ray when you click on left mouse button. Then both of them sends a ray from camera, using mouse position. Then these both rays hits and object or not;

  • In case they hit, they log the same hit object's name
  • In case they do not hit anything, they don't do anything.

A possible fix:

void Update () 
{
    if (Input.GetMouseButtonDown(0))
    {
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out hit) && hit.transform == transform)
        {
            if (hit.transform.name == "Object A")
            {
                Debug.Log("Object A Clicked");    // log twice
            }

            if (hit.transform.name == "Object B")
            {
                Debug.Log("Object B Clicked");   // log twice
            }
        }
    }
}

By adding "hit.transform == transform" in the if condition, you don't trigger the other object to log it. But still this is not an ideal solution since all of your objects sends ray and checks if the ray hit them.

A better approach is to send the ray from one central script and let that script tell object that it has been hit with a ray.