Нажатие кнопки Unity не срабатывает
Я посмотрел на пост, расположенный здесь, который посвящен той же проблеме, но он не иллюстрирует, что не так, и не решает мою проблему.
Я создал сборный Canvas с несколькими кнопками на панели. Я создаю экземпляр сборника во время выполнения и беру все Button
объекты внутри панели. Затем я добавляю слушателя к onClick()
событие для всех кнопок, вызывающих один и тот же clicked()
метод
public class GameOptions
{
private GameObject canvas;
public GameOptions(GameObject canvas)
{
this.canvas = canvas;
GameObject.Instantiate(canvas);
Text[] textObjects = canvas.GetComponentsInChildren<Text>();
Button[] buttonObjects = canvas.GetComponentsInChildren<Button>();
for (int i = 0; i < buttonObjects.Length; i++)
{
Debug.Log(buttonObjects[i].name);
buttonObjects[i].onClick.AddListener(() => clicked());
buttonObjects[i].onClick.Invoke();
}
}
public void clicked()
{
Debug.Log("Clicked!");
}
}
Обратите внимание, что когда я вызываю событие через код, clicked()
называется и "нажал!" правильно выводится на консоль.
Однако ни одна из кнопок не запускает событие при нажатии. Я также заметил, что массив PersistentCalls.Calls в OnClick в Inspector содержит 0 элементов для всех кнопок во время выполнения.
Я использую Unity 2017.4.3f1 в Windows 10 64.
2 ответа
Тот факт, что вы не бросаете никаких исключений, а onClick.Invoke()
Это наводит на мысль, что проблема в том, что какой-то другой элемент потребляет щелчки. Не имея вашего проекта передо мной, я могу только внести некоторые предложения.
- Убедитесь, что между камерой и кнопками нет элементов пользовательского интерфейса (таких как прозрачные панели или изображения); Вы можете перемещаться по объектам во время выполнения, чтобы увидеть, не слишком ли они близки и потребляют щелчок.
- Убедитесь, что родительский холст не имеет
CanvasGroup
сInteractable
установить в ложь. - Ищите любые пустые объекты / коллайдеры / слушатели, которые могут блокировать радиопередачи.
Удачи!
редактировать
После перечитывания вашего кода и повторного связанного поста я обнаружил ошибку в вашем коде.
В вашем GameOptions
конструктор класса, вы на самом деле не ссылаетесь на экземпляр объекта при сборе объектов. Это ты написал:
this.canvas = canvas;
GameObject.Instantiate(canvas);
Text[] textObjects = canvas.GetComponentsInChildren<Text>();
Если вы посмотрите, что именно происходит, вы назначаете поле canvas
в префаб, который был передан в параметр конструктора. После того, как вы сделаете присваивание, вы создаете экземпляр префаба с параметром, без какой-либо ссылки на экземпляр объекта.
После этого вы звоните GetComponentsInChildren
на префаб не сам экземплярный объект. Вот почему onClick.Invoke()
увольняют, потому что объекты существуют на сборном; они просто не те объекты, которые вы ищете.
Я реорганизовал ваш конструктор, который должен решить вашу проблему.
public GameOptions(GameObject canvas)
{
//here we instantiate the canvas item, assigning it to the field
this.canvas = GameObject.Instantiate(canvas);
//then we reference the field item, instead of the parameter item
Text[] textObjects = this.canvas.GetComponentsInChildren<Text>();
Button[] buttonObjects = this.canvas.GetComponentsInChildren<Button>();
for(int i = 0; i < buttonObjects.Length; i++)
{
Debug.Log(buttonObjects[i].name);
buttonObjects[i].onClick.AddListener(() => clicked());
buttonObjects[i].onClick.Invoke();
}
}
Несколько заметок
- Вы должны использовать
Canvas
предмет вместоGameObject
, даже если вы никогда не используете членовCanvas
учебный класс; это облегчает чтение в будущем и предотвращает случайное созданиеnew GameOptions(someRandomButton)
который просто ничего не сделает, когда вы попытаетесь получить доступ к детям.Canvas
объект наследуется отGameObject
так что у вас будет все, что вам нужно. - Вы должны рассмотреть возможность использования другой схемы именования; это очень субъективное мнение, и по этому вопросу много споров, если вы ищете SO. Лично я выбираю префикс подчеркивания в частных полях, таких как
private GameObject _canvas;
это заставляет меня не сомневаться, что я не забылthis
потому что по сути параметры и поля будут иметь различные и уникальные схемы именования.
Прими мой совет с крошкой соли! Существует много способов решения проблемы, поэтому в конечном итоге выберите наиболее удобный для вас вариант.
Просто чтобы помочь другим людям, столкнувшимся с этой досадной проблемой.
Помимо общих конфигурацийEventSystem
иCanvas
, есть еще одна причина неотзывчивости кнопок пользовательского интерфейса, которую я обнаружил в своих собственных программах, и я думаю, что она может быть причиной для большинства людей.
Проблема возникает, когда вы добавляете объект самостоятельно (очень часто), не помечая его. Если вы понятия не имеете, как его пометить, то, скорее всего, это ваша причина.
ключевой момент :camera
ты используешь сstandalone input module
должен быть помечен какMainCamera
. В противном случае он не распознает объекты без коллайдера.