Unity 4.6,如何阻止克隆共享监听器?

时间:2014-09-13 02:57:19

标签: c# unity3d listener

在Unity 4.6中尝试新的uGUI,编写按钮脚本...遍历目录并为每个文件创建一个按钮... AddListener位中的f.Name值应该为每个按钮独立设置。相反,每个按钮都具有要处理的最后一个f.Name的值(目录中按字母顺序排列的最后一个文件)。有什么想法吗?

foreach (FileInfo f in fileInfo) {
    Button btnCurrLvl = (Button) Instantiate(btnLvl);

    btnCurrLvl.GetComponentInChildren<Text>().text = f.Name.Remove(f.Name.Length-5);

    Debug.Log(f.Name); // f.Name is different every time
    btnCurrLvl.name = f.Name; // renaming the btns works
    btnCurrLvl.GetComponent<Button>().onClick.AddListener(() => LoadLocalLvl(f.Name)); // all the listeners on all created buttons are set to the last value of f.Name!?
}

2 个答案:

答案 0 :(得分:1)

在foreach循环中使用lambda表达式时要小心。以下代码:

var someList = new List<int> {1, 2, 3, 4};
var listOfClosures = new List<Func<int>>();
foreach (int v in someList)
{
    listOfClosures.Add( () => v );
}

(或多或少)等同于:

var someList = new List<int> {1, 2, 3, 4};
var listOfClosures = new List<Func<int>>();
int v;
for (int i = 0; i < someList.Count; i++)
{
    v = someList[i];
    listOfClosures.Add( () => v );
}

请注意,v声明在for循环的范围之外,然后仅在每次传递时重新分配。另请注意,闭包只保留对变量v的引用。因此,listOfClosures中的每个闭包在调用时都会返回4(最后一个值v被赋值)。

在你的情况下也是如此:

foreach (FileInfo f in fileInfo) {
    btnCurrLvl.GetComponent<Button>().onClick.AddListener(() => LoadLocalLvl(f.Name));
}

所有的闭包都会引用相同的f。 尝试在每个循环传递上创建新变量:

foreach (FileInfo f in fileInfo) {
    var name = f.Name;
    btnCurrLvl.GetComponent<Button>().onClick.AddListener(() => LoadLocalLvl(name));
}

答案 1 :(得分:0)

string captured;
foreach (FileInfo f in fileInfo) {
  Button btnCurrLvl = (Button) Instantiate(btnLvl);
  btnCurrLvl.GetComponentInChildren<Text>().text = f.Name.Remove(f.Name.Length-5);
  btnCurrLvl.name = f.Name;
  captured = f.Name;
  btnCurrLvl.GetComponent<Button>().onClick.AddListener(() => LoadLocalLvl(captured));
}

:)