Нажатие кнопки Unity не срабатывает - PullRequest
0 голосов
/ 29 мая 2018

Я посмотрел на сообщение , расположенное здесь , которое посвящено той же проблеме, но оно не иллюстрирует, что не так, и не исправляет мою проблему.

Я создал сборный 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.

1 Ответ

0 голосов
/ 29 мая 2018

Тот факт, что вы не выдает никаких исключений, а onClick.Invoke() срабатывает, говорит о том, что проблема заключается в том, что какой-то другой элемент потребляет щелчки.Не имея вашего проекта передо мной, я могу только внести некоторые предложения.

  • Убедитесь, что между камерой и кнопками нет элементов пользовательского интерфейса (таких как прозрачные панели или изображения);Вы можете перемещаться по объектам во время выполнения, чтобы увидеть, не слишком ли они близки и потребляют щелчок.
  • Убедитесь, что у родительского холста нет CanvasGroup с Interactable, установленным в false.
  • Найдите все пустые объекты / коллайдеры / слушатели, которые могут блокировать радиопередачи.

Удачи!


Редактировать

После повторногочитая ваш код и предоставляя связанный пост еще раз, я обнаружил ошибку в вашем коде.

В вашем конструкторе класса GameOptions вы фактически не ссылаетесь на экземпляр объекта при сборе объектов.Вы написали это:

this.canvas = canvas;
GameObject.Instantiate(canvas);
Text[] textObjects = canvas.GetComponentsInChildren<Text>();

Если вы просматриваете, что именно происходит, вы присваиваете поле canvas префабу, который был передан в параметр конструктора.После выполнения назначения вы создаете экземпляр префаба с параметром, без какой-либо ссылки на экземпляр объекта.

После этого вы вызываете GetComponentsInChildren для prefab , а не для экземпляра объектасам.Вот почему 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, потому что параметры и поля по своей сути будут иметь различные и уникальные схемы именования.

Прими мой совет с крошкой соли!Существует много способов решения проблемы, поэтому в конечном итоге выберите наиболее удобный для вас вариант.

...