Unity 5.3 onClick带参数问题

时间:2016-01-01 00:21:02

标签: unity3d unityscript

在我的游戏中,我以编程方式为级别选择屏幕创建了一组按钮,我的目的是让他们的onClick触发一个带有与级别编号对应的参数的函数。

伪代码:

m = MyCrazyClass.new(id: 231, first_name: "Joe", last_name: "Smith", age: 38, salary: BigDecimal.new("125000"))
m.get_first_name()  # returns Joe

serialized = Marshal::dump(m)
obj = Marshal::load(serialized)
obj.get_first_name()  # returns Joe

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

我如何实现我的目标?

1 个答案:

答案 0 :(得分:1)

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

您正在for循环中创建10个匿名函数。所有这些函数都引用局部变量level。但是,在首次调用它们之前,它们尚未为此变量创建自己的范围。这意味着,在实际调用第一个函数之前,没有10 level个本地,但只有一个。{1}}。只有这样才能评估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值。

工厂函数现在创建并返回您的匿名处理函数,即使它尚未创建自己的作用域,它也会引用封闭工厂函数的本地newLocalLevel,它对每次迭代都有一个单独的作用域循环。

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