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

如何修复Godot 4.3 C#中数组的不一致空引用异常

解决思路:Godot 4.3 C# 世界生成器空引用异常问题

核心问题定位

空引用异常出现在neighbourArray[0] = world.GetNodeOrNull(nameNW);,仅第一列Tile且存在BiomeType.None的Tile时触发,说明**neighbourArray本身未被初始化**的概率极高——当Tile被设置为Forest/Desert时,可能在赋值逻辑中顺带初始化了数组,但None类型的Tile跳过了这一步,导致调用FindNeighbours时数组为null,赋值时抛出异常。

具体排查与修复步骤

1. 强制初始化neighbourArray

检查TestTile类中neighbourArray的定义,确保所有Tile在调用FindNeighbours前都完成数组初始化:

  • 在TestTile的_Ready()方法中统一初始化数组,不依赖生物群类型:
public partial class TestTile : Node2D
{
    public Node2D[] neighbourArray;
    public YourGeneratorClass world; // 替换为你的主生成器类名
    public BiomeType biomeType = BiomeType.None;

    public override void _Ready()
    {
        // 固定初始化数组,确保所有Tile都有可用的数组实例
        neighbourArray = new Node2D[8];
    }

    // ... 其他方法
}

2. 修复Tile坐标解析的潜在bug

当前通过name[0] - '0'解析坐标仅支持个位数,当numOfTiles≥10时会解析错误,替换为可靠的分割方式:

public void FindNeighbours()
{
    GD.Print($"Tile {Name} with type {biomeType} finding neighbours: ");
    // 用Split分割坐标字符串,支持多位数索引
    var coordParts = Name.Split('-');
    int x = int.Parse(coordParts[0]);
    int y = int.Parse(coordParts[1]);

    int w = x - 1;
    int e = x + 1;
    int n = y - 1;
    int s = y + 1;

    // ... 后续邻居查找逻辑不变
}

3. 统一设置world变量,避免遗漏

将world的赋值从GiveBiomeTypes移到InitialiseGrid中,确保所有Tile创建时就关联主生成器,避免分情况赋值导致的遗漏:

IEnumerator<double> InitialiseGrid()
{
    int arrayIndex = -1;

    for (int x = 0; x < numOfTiles; x++)
    {
        for (int y = 0; y < numOfTiles; y++)
        {
            arrayIndex++;

            var newTile = tile.Instantiate<TestTile>(); // 直接实例化为TestTile
            AddChild(newTile);

            newTile.Position = new Vector2(x * sizeOfTiles, y * sizeOfTiles);
            newTile.Name = $"{x}-{y}";
            newTile.world = this; // 创建时直接设置world

            tilesArray[arrayIndex] = newTile;
        }
    }

    yield return Timing.WaitForSeconds(0.001f);
}

4. 清理冗余逻辑

GiveBiomeTypes中给None类型Tile赋值BiomeType.None是冗余操作,直接删除该代码块:

// 原冗余代码可直接删除
// int leftOvers = (numOfTiles * numOfTiles) - (numOfForest + numOfDesert);
// if (leftOvers > 0)
// {
//     for (int lo = 0; lo < leftOvers; lo++)
//     {
//         int rlo = GD.RandRange(0, tilesArray.Length - 1);
//         var slo = tilesArray[rlo] as TestTile;
//
//         if (slo.biomeType == BiomeType.None)
//         {
//             slo.biomeType = BiomeType.None; // 完全冗余
//             slo.world = this; // 已在InitialiseGrid中设置
//         }
//         else
//         {
//             lo--;
//         }
//     }
// }

5. 修复Desert赋值的笔误

GiveBiomeTypes中给Desert类型Tile错误赋值为Forest,修正:

if (numOfDesert > 0)
{
    for (int d = 0; d < numOfDesert; d++)
    {
        int rd = GD.RandRange(0, tilesArray.Length - 1);
        var sd = tilesArray[rd] as TestTile;

        if (sd.biomeType == BiomeType.None)
        {
            sd.biomeType = BiomeType.Desert; // 修正为Desert
        }
        else
        {
            d--;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:42:32