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
相关产品推荐
相关产品推荐

