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

本文关键字:共享 侦听器 何阻止 Unity | 更新日期: 2023-09-27 18:21:53

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

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!?
}

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

在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));
}
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));
}

:)