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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 06:29:56