Обнаружение объектов с помощью Raycast выполняется дважды

У меня есть два игровых объекта на моей сцене, и я назначаю этот сценарий им обоим. Когда я нажимаю на любой из них, код внутри оператора If, относящийся к каждому из них, выполняется дважды, если я отключаю один из них, он выполняется один раз, как и должен.

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

Вопрос в том, почему код выполняется дважды за один клик?!

3 ответа

Решение

Вопрос в том, почему код выполняется дважды за один клик?!

Потому что каждый Update () Функция из каждого скрипта называется каждый кадр. Input.GetMouseButtonDown(0) будет истинным в каждом кадре в каждом скрипте, который имеет его в функции обновления.

Если вы хотите, чтобы он обнаружил один раз, у вас есть два варианта:

1. Присоедините скрипт только к одному GameObject. Обычно пустой GameObject. Он должен обнаружить любой Gamebject с коллайдером один раз при нажатии.

2. Используйте IPointerDownHandler И его OnPointerDown функция. Вы можете прикрепить это к каждому GameObject, который вы хотите обнаружить, нажав. Проверьте #6 здесь для 2d/ спрайтов. Для 3D-объектов, проверьте #6.

Это выполняется дважды, потому что когда вы нажимаете на цель с помощью щелчка, это делает

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

Эта строка кода даст вам объект, и так как у вас есть сценарий в 2 объектах, он будет запускаться в 2 раза точно так же. Оба объекта получат одинаковые ray,

Он регистрировался дважды, потому что оба объекта посылают луч, когда вы щелкаете левой кнопкой мыши. Затем оба они посылают луч с камеры, используя положение мыши. Тогда оба эти луча бьют и объект или нет;

  • В случае попадания они регистрируют одно и то же имя объекта попадания
  • Если они ничего не бьют, они ничего не делают.

Возможное исправление:

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

Добавляя "hit.transform == transform" в условие if, вы не запускаете другой объект для его регистрации. Но все же это не идеальное решение, так как все ваши объекты посылают луч и проверяют, попал ли луч на них.

Лучший подход - отправить луч из одного центрального сценария и позволить этому сценарию сообщить объекту, что на него попал луч.

Другие вопросы по тегам