【问题标题】:How can I add each button created by script a on click listener event?如何添加由脚本创建的每个按钮单击侦听器事件?
【发布时间】:2019-06-07 20:00:57
【问题描述】:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GenerateUIButtons : MonoBehaviour
{
    public GameObject buttonPrefab;
    public GameObject parent;
    public int numberOfButtons;
    public float spaceBetweenButtons;

    private Button[] buttons;

    // Start is called before the first frame update
    void Start()
    {
        buttons = new Button[7];

        for (int i = 0; i < Rotate.names.Length; i++)
        {
            GameObject newButton = Instantiate(buttonPrefab);
            newButton.name = Rotate.names[i];
            newButton.transform.SetParent(parent.transform, false);
            buttons[i] = newButton.GetComponent<Button>();
            buttons[i].onClick.AddListener(() => ButtonClicked(i));
        }
    }

    void ButtonClicked(int buttonNo)
    {
        Debug.Log("Clicked On " + buttons[buttonNo]);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

我遇到了异常:

Debug.Log("Clicked On " + buttons[buttonNo]);

IndexOutOfRangeException: 索引超出数组范围

我想要做的是,当我点击其中一个按钮时,它会在 ButtonClicked 中执行相同的操作。

【问题讨论】:

  • 你能在它之前添加一个Debug.Log(buttonNo); 还是使用断点?
  • 和..你确定Rotate.names.Length总是7吗?为什么不使用硬编码而不是使用buttons = new Button[Rotate.names.Length];
  • 实际上,我会像 buttons[i].onClick.AddListener(() =&gt; ButtonClicked(newButton)); 一样直接传递 Button 引用并执行 void ButtonClicked(Button button) { Debug.Log("Clicked On " + button); } 。并作为提示:如果您将预制件的类型直接更改为public Button buttonPrefab;,则不需要使用GetComponent

标签: c# unity3d


【解决方案1】:

这是一个闭包问题,不要使用循环值来创建闭包,先将值赋给另一个局部变量。

for (int i = 0; i < Rotate.names.Length; i++)
{
    ...
    int j = i;
    buttons[i].onClick.AddListener(() => ButtonClicked(j));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-03
    • 2012-11-26
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    相关资源
    最近更新 更多