最近开发受难日的时候遇到一个小问题。
我有3个按钮,它们的功能相似,在被点击时需要为一个字段赋不同的值,分别是0,1,2。我在一个脚本里通过委托的方式为这三个按钮的OnClick事件添加带有不同参数的委托,代码如下。
1 | using System.Collections; |
结果发现三个按钮点击的输出都是3,这就很奇怪了。3应该是Start里循环结束后i的值,而i作为整型应该是按值传递而非按引用传递的,怎么会三个按钮的参数全部引用的同一个变量上了呢。
后来在Unity论坛发帖问了之后(包括查阅了一下其他的Post),发现原来在C#中使用匿名委托时,会捕捉本地调用方法的完整上下文,也就意味着OnSelect的参数实际上保留着对Start方法里的i的饮用,这也是为什么三个按钮输出相同的原因。
如果要避免这一点,就应该让不同的按钮事件捕捉不同的上下文,或者是引用不同的变量。
前者可以通过下列方式实现:1
2
3
4
5
6
7void Start(){
for(int i=0; i < 3; i++){
int index = new int();
index = i;
buttons[i].onClick.AddListener(delegate { OnSelect(i); });
}
}
后者通过创建一个新的添加监听的函数并将i作为参数传递实现:1
2
3
4void AddListener(Button button, int parameter)
{
button.onClick.AddListener(delegate { OnSelect(parameter); });
}
相关链接: