Unity onClick.addlistener не работает

Я загружаю префаб Canvas во время выполнения, когда происходит событие. Холст просто имеет панель внутри, которая в свою очередь имеет 2 кнопки. Я пытаюсь добавить события OnClick для обеих этих кнопок в сценарии, но как-то работает только для первой кнопки! У меня есть следующие две строки кода одна за другой:

GameObject.Find("RestartButton").GetComponent<Button>().onClick.AddListener(() => RestartClicked());
GameObject.Find("ViewButton").GetComponent<Button>().onClick.AddListener(() => ViewClicked());

Обратный вызов работает только для RestartButton, а не для ViewButton. Это может быть очень маленькая вещь, но я много искал в Google и Bing и остался в неведении, поэтому любая помощь будет принята с благодарностью.

Спасибо!

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

Скрипт создает экземпляр префаба и пытается сослаться на две кнопки в префабе через GameObject.Find(), учитывая, что после вызова Instantiate Canvas должен быть активен в иерархии. Я также открыл часть кода, которая прикрепляет кнопки к слушателю для отладки. Я не думаю, что это присоединяет слушателя вообще.

void Start () {

    SetupScene();

    var prefab = Resources.Load("RestartOrViewPrefab");
    if (prefab == null)
    {
        Debug.LogAssertion("Prefab missing!");
        return;
    }
    restartCanvas = (GameObject)Instantiate(prefab);
    Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
    btn.onClick.RemoveAllListeners();
    btn.onClick.AddListener(() => ViewToggle());
    Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
    btn2.onClick.AddListener(() => RestartClicked());
}

private void RestartClicked()
{
    Debug.Log("RESTARTING");
    SetupScene();
}

private void ViewToggle()
{
    Debug.Log("TOGGLE");
    if (freshStart)
    {
        //Something here
        freshStart = false;
    }
    else
    {
        //Something else here
        freshStart = true;
    }
}

3 ответа

Решение

Таким образом, я занял два дня, чтобы решить мою проблему. Видимо, делает GameObject.Find() для GameObject внутри префаба, который вы только что создали, не работает. Нам всегда нужно использовать GameObject, чтобы Instantiate() Метод возвращает, чтобы найти любой компонент в префабе. Код, который я использовал, чтобы заставить мою сцену работать, может быть не лучшим решением, если ваш префаб очень большой / сложный (скажем, у вас есть 15 кнопок и вам нужно что-то с ними сделать), но он, безусловно, работает.:) Я заменил следующие строки кода:

Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => ViewToggle());
Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
btn2.onClick.AddListener(() => RestartClicked());

Со следующими строками кода:

Button[] buttons = restartCanvas.GetComponentsInChildren<Button>();

    foreach(Button but in buttons)
    {
        if(but.gameObject.name == "RestartButton")
            but.onClick.AddListener(() => RestartClicked());
        else if(but.gameObject.name == "ViewButton")
            but.onClick.AddListener(() => ViewToggle());
    }

Так что я просто использовал restartCanvas что я получил ссылку.

restartCanvas = (GameObject)Instantiate(prefab);

Надеюсь, это кому-нибудь поможет.:)

Я ответил на это в другом посте, но я отвечу здесь для людей, которым все еще нужна эта информация. GameObject, экземпляр которого вы создали, является дочерним элементом, на котором должен быть компонент CanvasRenderer. Я не уверен, почему это работает, но это работает. Когда родитель кнопки GameObject имеет CanvasRenderer, вы можете вызвать myButton.onClick.AddListener(() => MyMethod(MyArgs)); как обычно.

Хорошо, убедитесь, что у вас нет ошибки нулевой ссылки, и проверьте правильность написания ваших кнопок, выведите несколько журналов отладки во вторую функцию, чтобы увидеть, достигла ли она там чего-либо.

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