0

我在代码中添加了一个按钮列表,我想为其添加一个点击监听器。

我可以添加监听器,问题是我想知道调用监听器的按钮。

我尝试了以下方法,但是传递给侦听器的值始终相同:

foreach (...)
{
    var button = (Button)GameObject.Instantiate(...);

    packIndex++;

    button.onClick.AddListener(() => this.OnButtonClick(packIndex));
}

public void OnButtonClick(int idx)
{
    // idx is always the latest value in the above loop
}

TL;博士

您如何从按钮单击侦听器中找到调用者?

4

2 回答 2

1

尝试这个

var button = (Button)GameObject.Instantiate(...);
packIndex++;
button.name = "Button" + packIndex;
button.onClick.AddListener(() => this.OnButtonClick(button));

public void OnButtonClick(Button button)
{
// idx is always the latest value in the above loop
}
于 2015-08-16T17:36:04.327 回答
1

你几乎拥有它。packIndex要存储索引,您需要通过在 for 循环内制作副本来“捕获”packIndex 变量。您可以在此处看到对这种“for 循环中的闭包”现象的一个很好的解释。

以下代码应该可以工作:

foreach (...)
{
    var button = (Button)GameObject.Instantiate(...);

    packIndex++;
    var packIndexCopy = packIndex;

    button.onClick.AddListener(() => this.OnButtonClick(packIndexCopy));
}

public void OnButtonClick(int idx)
{
    // idx is always the latest value in the above loop
}

请注意,@Nain 的答案也将起作用,因为在这种情况下,“按钮”对象AddListener(() => this.OnButtonClick(button));指的是每次在 foreach 循环中创建的新对象,因此编译器会将OnButtonClick处理程序正确绑定到该“新”副本。事实上,Button直接传递对象感觉更干净一些,但这取决于你的代码的其余部分。

如果你对闭包不熟悉(这真的很混乱,需要很长时间才能理解!),这篇文章有一个很好的解释。

PS我写了一个小组件来测试它,这里是它的要点,以防它有帮助。

于 2015-08-16T17:49:25.323 回答