如何修复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
相关产品推荐
相关产品推荐

