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

Unity关卡选择按钮索引异常:点击始终返回最后索引

解决Unity关卡选择按钮索引错误的问题

你遇到的是闭包捕获变量的常见陷阱:在foreach循环中,委托捕获的是index变量的引用而非当前迭代的数值。循环结束后index的值已经等于imageTextures的总长度,所以所有按钮点击都会输出这个最终值。

下面是几种解决方法和更优实现方案:

方法一:循环内创建局部变量捕获当前值

在foreach循环内部,用局部变量保存当前迭代的索引和纹理,让委托捕获这些局部值,避免引用同一个外部变量:

void Start()
{
    int index = 0;
    foreach (Texture2D texture in imageTextures)
    {
        // 用局部变量保存当前迭代的索引和纹理
        int currentIndex = index;
        Texture2D currentTexture = texture;
        
        Image image = Instantiate(levelSelectPrefab, levelSelectPanel);
        Button button = image.GetComponent<Button>();
        button.onClick.AddListener(delegate { StartGame(currentTexture, currentIndex); });
        index++;
    }
}

public void StartGame(Texture2D jigsawTexture, int index)
{
    Debug.Log("chosen puzzle index: " + index);
}

方法二:改用for循环替代foreach

C# 5.0及以上版本中,for循环的迭代变量会在每次循环时重新创建,委托会捕获当前迭代的数值而非引用,直接使用即可:

void Start()
{
    for (int index = 0; index < imageTextures.Length; index++)
    {
        Texture2D texture = imageTextures[index];
        Image image = Instantiate(levelSelectPrefab, levelSelectPanel);
        Button button = image.GetComponent<Button>();
        button.onClick.AddListener(delegate { StartGame(texture, index); });
    }
}

public void StartGame(Texture2D jigsawTexture, int index)
{
    Debug.Log("chosen puzzle index: " + index);
}

更优实现:UI与数据绑定

创建独立的关卡项脚本,将索引、纹理等数据直接挂载到UI对象上,逻辑更清晰且便于后期扩展:

  1. 新建LevelItem脚本:
using UnityEngine;
using UnityEngine.UI;

public class LevelItem : MonoBehaviour
{
    public int levelIndex;
    public Texture2D levelTexture;
    private Button _levelButton;

    private void Awake()
    {
        _levelButton = GetComponent<Button>();
        _levelButton.onClick.AddListener(OnLevelClicked);
    }

    private void OnLevelClicked()
    {
        // 可直接调用游戏逻辑方法,或通过单例/事件通知
        // 示例:假设存在GameManager单例
        GameManager.Instance.StartGame(levelTexture, levelIndex);
    }
}
  1. 修改Start方法:
void Start()
{
    for (int index = 0; index < imageTextures.Length; index++)
    {
        Image image = Instantiate(levelSelectPrefab, levelSelectPanel);
        LevelItem levelItem = image.GetComponent<LevelItem>();
        if (levelItem != null)
        {
            levelItem.levelIndex = index;
            levelItem.levelTexture = imageTextures[index];
        }
    }
}

// GameManager中的示例方法
public void StartGame(Texture2D jigsawTexture, int index)
{
    Debug.Log("chosen puzzle index: " + index);
}

这种方式将UI元素与对应的数据、逻辑绑定,后续添加关卡锁定、星级展示等功能时,只需在LevelItem中扩展即可,维护性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:02:49