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

Unity遍历列表时onClick.AddListener()失效,点击均触发最后一项数据

问题原因

循环中用闭包绑定按钮事件时,捕获的是变量i的引用,而非当前迭代的具体值。等所有按钮创建完成、循环结束后,i的值已经变成inventoryT1.Container.Count,此时点击任何按钮,i-1都会指向列表最后一项的索引,导致所有按钮都加载最后一个物品的数据。

解决办法

方法1:循环内创建局部变量保存当前物品/索引

在每次循环迭代中,把当前的物品对象或索引存入一个局部变量,让闭包捕获这个独立的变量,避免引用共享:

保存物品对象的写法

for (int i = 0; i < inventoryT1.Container.Count; i++)
{
    // 保存当前迭代的物品对象
    PrisonerObject currentPrisoner = inventoryT1.Container[i].item;
    GameObject obj = Instantiate(currentPrisoner.DefaultPrefab, Vector3.zero, Quaternion.identity, transform);
    
    obj.GetComponent<RectTransform>().localPosition = GetPosition(i);
    obj.GetComponentInChildren<TextMeshProUGUI>().text = inventoryT1.Container[i].level.ToString();

    // 绑定事件时使用局部变量currentPrisoner
    obj.GetComponent<Button>().onClick.AddListener(() => LoadPrisonerStore(currentPrisoner));
}

保存索引的写法

for (int i = 0; i < inventoryT1.Container.Count; i++)
{
    int currentIndex = i;
    GameObject obj = Instantiate(inventoryT1.Container[currentIndex].item.DefaultPrefab, Vector3.zero, Quaternion.identity, transform);
    
    obj.GetComponent<RectTransform>().localPosition = GetPosition(currentIndex);
    obj.GetComponentInChildren<TextMeshProUGUI>().text = inventoryT1.Container[currentIndex].level.ToString();

    obj.GetComponent<Button>().onClick.AddListener(delegate { LoadPrisonerStore(inventoryT1.Container[currentIndex].item); });
}

方法2:给UI对象绑定自定义组件存储物品数据

如果想用ReturnObject(obj)的方式,可以给每个生成的UI对象添加一个自定义组件,用来存储对应的物品数据,后续通过组件获取:

步骤1:创建自定义组件

using UnityEngine;

public class PrisonerItemUI : MonoBehaviour
{
    public PrisonerObject prisonerData; // 存储当前UI对应的物品数据
}

步骤2:循环中赋值组件并绑定事件

for (int i = 0; i < inventoryT1.Container.Count; i++)
{
    PrisonerObject currentPrisoner = inventoryT1.Container[i].item;
    GameObject obj = Instantiate(currentPrisoner.DefaultPrefab, Vector3.zero, Quaternion.identity, transform);
    
    obj.GetComponent<RectTransform>().localPosition = GetPosition(i);
    obj.GetComponentInChildren<TextMeshProUGUI>().text = inventoryT1.Container[i].level.ToString();

    // 添加或获取自定义组件,存入物品数据
    PrisonerItemUI itemUI = obj.GetComponent<PrisonerItemUI>();
    if (itemUI == null)
    {
        itemUI = obj.AddComponent<PrisonerItemUI>();
    }
    itemUI.prisonerData = currentPrisoner;

    // 绑定ReturnObject方法
    obj.GetComponent<Button>().onClick.AddListener(() => ReturnObject(obj));
}

步骤3:修改ReturnObject方法获取数据

public void ReturnObject(GameObject obj)
{
    PrisonerItemUI itemUI = obj.GetComponent<PrisonerItemUI>();
    if (itemUI != null && itemUI.prisonerData != null)
    {
        LoadPrisonerStore(itemUI.prisonerData);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 12:05:29