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

Unity动态生成按钮点击触发ArgumentOutOfRangeException异常

问题根因

这是C#循环绑定事件时的闭包变量捕获经典问题,和目标业务函数、buttonActions列表初始化逻辑无关。
你在循环生成按钮、绑定点击回调的逻辑中,直接捕获了循环迭代用的索引变量。回调实际触发(用户点击生成的按钮)时,循环逻辑早已执行完毕,此时索引变量的值为循环终止后的数值:你本次生成1个按钮,循环结束后索引值自增为1,而长度为1的buttonActions列表合法索引范围仅为0,访问索引1自然触发ArgumentOutOfRangeException。
场景中手动放置的按钮不存在循环绑定的变量捕获逻辑,因此调用目标函数完全正常。

修复方案
  • 循环内声明临时变量拷贝当前索引,回调绑定该临时变量而非直接捕获循环迭代变量,参考代码如下:
// 原错误写法(对应脚本第86行的问题逻辑)
for (int i = 0; i < categoryButtonConfigs.Count; i++)
{
    Button newBtn = Instantiate(buttonPrefab, buttonContainer);
    // 直接捕获循环变量i,点击触发时i已变为循环结束后的终值
    newBtn.onClick.AddListener(() => buttonActions[i].Invoke());
}

// 修复后写法
for (int i = 0; i < categoryButtonConfigs.Count; i++)
{
    int currentIndex = i; // 每次循环迭代独立持有当前索引值,不受后续循环自增影响
    Button newBtn = Instantiate(buttonPrefab, buttonContainer);
    newBtn.onClick.AddListener(() => buttonActions[currentIndex].Invoke());
}
  • 更稳妥的写法:生成按钮时直接持有当前要绑定的Action委托,回调直接触发持有的委托,完全绕开索引访问逻辑,从根源避免索引问题:
for (int i = 0; i < categoryButtonConfigs.Count; i++)
{
    Button newBtn = Instantiate(buttonPrefab, buttonContainer);
    Action clickAction = buttonActions[i];
    newBtn.onClick.AddListener(() => clickAction.Invoke());
}
验证方法

修复后可在按钮点击回调内加日志打印当前访问的索引值,点击"Next Song"按钮时日志输出索引为0即符合预期,可正常调用切歌逻辑,不会再抛出索引越界异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 10:01:00