Unity3D中访问Item类ID字符串时出现StackOverflowError求助
问题原因分析
StackOverflowError的直接原因是addItem方法中的无限递归调用:
- 在
addItem的第二个foreach循环中,当处理"filler"物品且物品数量超过堆叠上限时,代码执行addItem(f),其中f是当前inventory中被修改后的"filler"物品。 - 进入递归的
addItem方法后,第一个foreach会匹配所有id为"filler"的物品(也就是整个inventory里的初始物品),处理后第二个foreach又会再次触发递归调用,形成无限循环,最终耗尽栈内存抛出StackOverflowError。
此外代码还存在其他逻辑问题,会加剧错误:
- 第一个foreach循环中,合并物品后未将
add.amount清零,导致后续循环重复处理剩余数量。 - 处理"filler"物品时,混淆了待添加物品和容器物品的角色,错误地将容器物品作为新的待添加物品传入递归。
修复方案
1. 修正递归逻辑,避免无限调用
移除错误的递归调用,调整addItem的逻辑流程,优先堆叠到已有同id物品,再处理剩余数量:
public void addItem(item add) { // 先尝试堆叠到已有同id物品中 int i = 0; foreach(item x in items) { if (x != null && x.id == add.id && add.amount > 0) { int availableSpace = x.stacksize - x.amount; if (availableSpace >= add.amount) { x.amount += add.amount; add.amount = 0; break; // 数量已全部处理,直接退出循环 } else { x.amount = x.stacksize; add.amount -= availableSpace; } } i++; } // 如果还有剩余数量,寻找空的filler位置替换 if (add.amount > 0) { i = 0; foreach(item x in items) { if (x != null && x.id == "filler") { items[i] = add; add.amount = 0; break; } i++; } } }
2. 修正初始化逻辑
原init方法用foreach遍历未初始化的数组,改为for循环更清晰可靠:
public void init() { for (int i = 0; i < items.Length; i++) { item e = new item(); e.stacksize = 1; e.amount = 1; e.id = "filler"; items[i] = e; } }
3. 添加空引用防护
在printInv中添加空检查,避免空指针异常:
public void printInv() { foreach (item n in items) { if (n != null) { PlayerController.print(n.id + " | " + n.amount); } else { PlayerController.print("Empty | 0"); } } }
额外优化建议
- 遵循C#命名规范:类名首字母大写(改为
Item和Inventory),字段/属性使用驼峰或帕斯卡命名。 - 将"filler"定义为常量,避免硬编码字符串:
private const string FillerId = "filler"; - 考虑将物品堆叠逻辑封装到
Item类中,让职责更单一。
内容的提问来源于stack exchange,提问作者RedDev
相关产品推荐
相关产品推荐

