Получить ссылку на функцию для выполнения из инспектора единства для OnClick динамически созданной кнопки.

Я хочу знать, как я могу получить ссылку на конкретную функцию в любом другом скрипте через инспектора единства, чтобы добавить ее в прослушиватель щелчка динамически создаваемой кнопки. Я попробовал общедоступное UnityEvent, чтобы получить ссылку на функции (точно так же, как при нажатии статической кнопки), но я не уверен, как добавить его в прослушиватель при нажатии (button.onClick.AddListener(functionName)) как прослушиватель выглядит для действия. Есть ли что-то, что я упускаю? Или есть какой-то другой подход к этому? Спасибо. Это идея -

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class DynamicButton : MonoBehaviour
{
    public Button MainButton;
    public GameObject ButtonPrefab;

    [System.Serializable]
    public class ButtonInfo
    {
        public Sprite sprite;
        public UnityEvent ButtonEvent; //take reference to a particular function
    }
    public ButtonInfo[] ButtonCount;

    void Start()
    {
        PlaceButtons();

    }

    void PlaceButtons()
    {

        int NoButton = ButtonCount.Length;

        for (int i = 0; i < NoButton; i++)
        {           
            Vector3 newPos = new Vector3(i*10, i*10,0);   
            GameObject go = Instantiate(ButtonPrefab, newPos, Quaternion.identity);
            go.GetComponent<Image>().sprite = ButtonCount2To6[i].sprite;
            go.GetComponent<Button>().onClick.AddListener();  //This is where I want to add the  particular function that i want to execute when the button is clicked
            go.transform.parent = MainButton.transform;
            go.transform.localPosition = newPos;
        }
    }
}

person kewal kishan    schedule 13.10.2018    source источник
comment
Не могли бы вы добавить код того, что у вас есть, чтобы понять, что именно вы пытаетесь заархивировать? И почему это должно происходить в инспекторе явно?   -  person derHugo    schedule 13.10.2018
comment
@derHugo хорошо, добавлю код, который я пытался.   -  person kewal kishan    schedule 13.10.2018
comment
@derHugo, я надеюсь, что это прояснит мой вопрос.   -  person kewal kishan    schedule 13.10.2018


Ответы (1)


Что вам нужно сделать, так это Invoke событие вместо добавления его к событию onClick. Вам не нужно узнавать/копировать слушателей каждого UnityEvent, но вместо этого достаточно вызвать UnityEvent. Затем UnityEvent вызывает всех своих слушателей, которых вы назначили, например. в Инспекторе. Это можно сделать с помощью простой лямбда-функции:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class DynamicButton : MonoBehaviour
{
    public Button MainButton;
    public GameObject ButtonPrefab;

    [Serializable]
    public class ButtonInfo
    {
        public Sprite sprite;
        public UnityEvent ButtonEvent; //take reference to a particular function
    }

    public ButtonInfo[] ButtonCount;

    private void Start()
    {
        PlaceButtons();
    }

    private void PlaceButtons()
    {
        int NoButton = ButtonCount.Length;

        for (int i = 0; i < NoButton; i++)
        {           
            Vector3 newPos = new Vector3(i*10, i*10, 0);   
            GameObject go = Instantiate(ButtonPrefab, newPos, Quaternion.identity);

            // What is ButtonCount2To6?? It probably should rather be ButtonCount[i] ?
            go.GetComponent<Image>().sprite = ButtonCount2To6[i].sprite; 


            // since the lambda will have no acces to i you have to get the reference to the according ButtonInfo first
            var accordingButtonInfo = ButtonCount[i];

            // Add the Invoke call as lambda method to the buttons
            go.GetComponent<Button>().onClick.AddListener(() => {
                accordingButtonInfo .ButtonEvent.Invoke();
            });  

            go.transform.parent = MainButton.transform;
            go.transform.localPosition = newPos;
        }
    }
}

см. также этот пост

person derHugo    schedule 13.10.2018
comment
Привет! Я получаю исключение IndexOutOfRangeException: индекс массива выходит за пределы диапазона, когда я нажимаю на динамически созданные кнопки. Ошибка возникает в строке функции Invoke(). Любая идея, почему? - person kewal kishan; 13.10.2018
comment
Эй, извини, я забыл, что лямбда не будет иметь доступа к i. Вы должны получить ссылку на ButtonCount[i] раньше. Смотрите мое обновление - person derHugo; 13.10.2018
comment
Ох, ладно ! Я заработал, добавив числовое имя к динамическим кнопкам и используя его для вызова правильной функции. Большое спасибо! @derHugo - person kewal kishan; 13.10.2018
comment
@kewalkishan Обратите внимание, что метод addListener может также ссылаться на именованные функции. Просто делегат или лямбда более гибкие. - person Draco18s no longer trusts SE; 13.10.2018