Обнаружение объектов с помощью 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, вы не запускаете другой объект для его регистрации. Но все же это не идеальное решение, так как все ваши объекты посылают луч и проверяют, попал ли луч на них.
Лучший подход - отправить луч из одного центрального сценария и позволить этому сценарию сообщить объекту, что на него попал луч.