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

Unity中List<GameObject>.IndexOf始终返回-1的问题求助

问题分析与解决方案

核心问题原因

StoredObj.IndexOf(InvObj)返回-1,本质是引用类型的相等性检查不通过——Unity的GameObject是引用类型,IndexOf默认对比对象引用,而非名称或其他属性。即使两个对象同名、外观一致,只要不是同一个内存实例,就会返回-1。

针对性解决办法

1. 修复引用匹配问题

  • 避免依赖对象名称传递引用:不要通过Find、实例化克隆等方式获取InvObj,确保传入的InvObj就是StoredObj列表中存储的那个实例。
  • 改用唯一标识匹配:给每个GameObject添加自定义ID组件(比如ItemID),存储唯一字符串或整数,遍历列表对比ID来定位索引:
    int GetObjIndex(GameObject targetObj)
    {
        ItemID targetID = targetObj.GetComponent<ItemID>();
        for(int i=0; i<StoredObj.Count; i++)
        {
            ItemID storedID = StoredObj[i].GetComponent<ItemID>();
            if(storedID != null && storedID.ID == targetID.ID)
            {
                return i;
            }
        }
        return -1;
    }
    

2. 优化代码逻辑,避免重复索引查找与列表错位

原代码存在两个关键问题:多次重复调用IndexOf浪费性能,且移除StoredObj元素时未同步处理ObjAmount,导致后续列表索引对应关系错乱。优化后的代码:

public void RemoveObjInv(GameObject InvObj, int amount)
{
    ChangeObjTag InvObjScript = InvObj.GetComponent<ChangeObjTag>();
    if (InvObjScript?.Stored != true)
    {
        return;
    }

    int targetIndex = StoredObj.IndexOf(InvObj);
    if (targetIndex == -1)
    {
        Debug.LogError($"无法找到对象 {InvObj.name} 在StoredObj列表中");
        return;
    }

    ObjAmount[targetIndex] -= amount;
    if (ObjAmount[targetIndex] <= 0)
    {
        // 同步移除两个列表的对应元素,避免索引错位
        ObjAmount.RemoveAt(targetIndex);
        StoredObj.RemoveAt(targetIndex);
        // 直接使用传入的InvObj,无需Find(避免同名对象混淆)
        InvObj.SetActive(false);
    }
}

3. 排查引用失效场景

  • 检查是否存在场景卸载、对象销毁后重新加载的情况:这种场景下原引用会失效,需用DontDestroyOnLoad保留跨场景对象引用,或使用Unity Addressables管理对象实例。
  • 用Object.ReferenceEquals(InvObj, storedObj)手动验证引用一致性,确认传入的对象和列表中的对象是否为同一实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:05:10