使用委托添加Button侦听器以停止更新方法参数

时间:2020-06-24 07:02:00

标签: c# unity3d button delegates

假设我在Unity中有一个画布,我想在其中创建5个按钮。每次按下按钮时,它都会显示This is button n.i,其中i从0到4。这是我到目前为止一直在使用的代码:

public Button buttonPrefab; //set from inspector
void SetButtons()
{
    Button newObj;
    for (int i = 0; i < 5; i++)
    { //loop 5 times, creates a button using buttonPrefab and assign ButtonNumber() method to it
        newObj = Instantiate(buttonPrefab, transform);
        newObj.onClick.AddListener(delegate { ButtonNumber(i); });
    }
}
void ButtonNumber(int nButton)
{
    Debug.Log($"This is button n.{nButton}");
}

我使用onClick.AddListener为按钮分配一个方法,并且由于该方法需要参数,因此我一直使用delegate来传递它们。

问题在于,对于我按下的每个按钮,结果始终为This is button n.5

所有按钮似乎总是根据i的最新值进行更新,即使我希望方法在分配i值时也要保存它。

我可以使用以下脚本来使脚本工作:

public Button buttonPrefab; //set from inspector
void SetButtons()
{
    Button newObj;
    for (int i = 0; i < 5; i++)
    {
        newObj = Instantiate(buttonPrefab, transform);
        switch (i)
        {
            case 0:
                newObj.onClick.AddListener(delegate { ButtonNumber(0); });
                break;
            case 1:
                newObj.onClick.AddListener(delegate { ButtonNumber(1); });
                break;
            case 2:
                newObj.onClick.AddListener(delegate { ButtonNumber(2); });
                break;
            case 3:
                newObj.onClick.AddListener(delegate { ButtonNumber(3); });
                break;
            case 4:
                newObj.onClick.AddListener(delegate { ButtonNumber(4); });
                break;
        }
    }
}
void ButtonNumber(int nButton)
{
    Debug.Log($"This is buton n.{nButton}");
}

但是我不会将其称为“智能”解决方案。

我可以做些什么使按钮在第一个脚本中起作用吗?

1 个答案:

答案 0 :(得分:1)

只需更改为:

  var x = i;
  newObj.onClick.AddListener(delegate { ButtonNumber(x); });

Voila。

发生的事情称为i变量的“捕获”,您可以在其中找到大量的问题和答案,例如: Captured variable in a loop in C#