You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中循环创建按钮,如何让UnityAction绑定正确的变量参数?

解决Unity循环实例化按钮时所有点击都传递同一参数的问题

这是典型的闭包捕获变量引用导致的问题:循环中创建的Lambda表达式并没有捕获循环变量i的当前值,而是捕获了i变量本身的引用。当循环执行完毕,i的值已经递增到6,所以所有按钮点击时都会调用PlayLevel(6)。

下面提供几种可行的解决方法:

方法一:使用局部变量保存当前循环值

在循环内部创建一个独立的局部变量,保存当前i的数值,让Lambda捕获这个局部变量的引用:

for (int i = 1; i <= 5; i++)
{
    GameObject button = Instantiate(buttonPrefab, buttonParent.transform);
    // 用局部变量保存当前循环的i值
    int currentLevel = i;
    UnityAction action = new UnityAction(() => PlayLevel(currentLevel));
    button.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(action);
}

每次循环都会生成一个独立的currentLevel,每个按钮的Lambda都会绑定到属于自己的变量,不会被后续循环的变量值覆盖。

方法二:利用UnityAction的泛型重载

Unity提供了带参数的UnityAction<T>重载,可以直接绑定带参数的方法,核心还是要通过局部变量捕获当前值:

for (int i = 1; i <= 5; i++)
{
    GameObject button = Instantiate(buttonPrefab, buttonParent.transform);
    int currentLevel = i;
    // 直接使用带参数的Lambda绑定
    button.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(() => PlayLevel(currentLevel));
}

这种写法更简洁,本质和方法一逻辑一致。

方法三:组件化存储参数(推荐)

创建一个自定义脚本组件,把关卡参数存在按钮对象上,通过组件内部的方法调用PlayLevel,更符合Unity的组件化设计:

首先创建LevelButton.cs脚本:

using UnityEngine;
using UnityEngine.UI;

public class LevelButton : MonoBehaviour
{
    public int level;

    // 按钮点击时触发的方法
    public void OnLevelButtonClick()
    {
        PlayLevel(level);
    }

    // 你的关卡加载方法
    private void PlayLevel(int level)
    {
        Debug.Log($"开始加载关卡:{level}");
        // 这里写你的关卡加载逻辑
    }
}

然后在循环中给每个按钮添加组件并赋值:

for (int i = 1; i <= 5; i++)
{
    GameObject button = Instantiate(buttonPrefab, buttonParent.transform);
    LevelButton levelBtn = button.AddComponent<LevelButton>();
    levelBtn.level = i;
    // 绑定组件内的点击方法
    button.GetComponent<Button>().onClick.AddListener(levelBtn.OnLevelButtonClick);
}

这种方式不仅避免了闭包问题,还方便后续扩展按钮功能(比如显示关卡名称、解锁状态等)。

内容的提问来源于stack exchange,提问作者Robin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:45:14