Unity 5.3 onClick 参数问题

Unity 5.3 onClick with parameters issue

在我的游戏中,我以编程方式为关卡 select 屏幕创建了一堆按钮,我的目的是让它们的 onClick 触发一个函数,其参数对应于关卡编号。

伪代码:

public class UIManager extends MonoBehaviour {
    public var button : Transform;

    public function Start() {
        for(var i : int = 0; i < 10; i++) {
            var level : int = i + 1;
            var b : Transform = Instantiate(button);

            b.GetComponent(UI.Button).onClick.AddListener(function(){
                StartGame(level);
            });
        }
    }

    public function StartGame(level : int) {
        Debug.Log(level);
    }
}

但是,在这种情况下,当按下这些按钮中的任何一个时,控制台会显示数字 10。

我怎样才能实现我的目标?

您应该看看 JavaScript 中的匿名函数如何捕获外部变量。

您正在 for-loop 中创建 10 个匿名函数。所有这些函数都引用局部变量level。但是,在第一次调用它们之前,它们还没有为此变量创建自己的范围。这意味着,没有 10 level 个局部变量,只有一个,直到第一个函数被实际调用。只有这样才会评估 level 的当前值。这将是最后分配的值:10.

要解决这个问题,您必须在循环的每次迭代期间强制创建一个新范围:

public class UIManager extends MonoBehaviour
{
    public var button : Transform;

    public function Start()
    {
        for(var i : int = 0; i < 10; i++)
        {
            var level : int = i + 1;
            var b : Transform = Instantiate(button);

            b.GetComponent(UI.Button).onClick.AddListener
            (
                (function(newLocalLevel)
                {
                    return function()
                    {
                        StartGame(newLocalLevel);
                    };
                }) (level)
            );
        }
    }

    public function StartGame(level : int)
    {
        Debug.Log(level);
    }
}

我将您对匿名处理程序函数的直接分配更改为工厂函数调用,它将 level 的当前 (!) 值作为参数。当它被立即执行时,工厂函数创建了自己的作用域,有一个名为 newLocalLevel 的局部作用域,其中包含 level.

的正确值

工厂函数现在创建并 returns 您的匿名处理程序函数,即使它尚未创建自己的作用域,它也引用封闭工厂函数的局部 newLocalLevel,它具有循环的每次迭代都有一个单独的范围。

另见 http://www.mennovanslooten.nl/blog/post/62