【发布时间】:2012-08-16 21:58:31
【问题描述】:
我正在使用一个锯齿状数组来保存我正在制作的游戏中的地图片段(集群)。数组中的位置对应于集群在地图中的位置。此外,如果内部数组(锯齿状部分)不再加载任何集群(集群在未使用的超时后从数组中删除),则外部数组的元素设置回 null 以保持地图的内存使用下来。
当游戏试图从地图中获取集群时,问题似乎是随机出现的:
public Cluster getCluster(int xIndex, int yIndex)
{
lock (xAxis)
{
loadCluster(xIndex, yIndex);
return xAxis[xIndex][yIndex];
}
}
public void loadCluster(int xIndex, int yIndex)
{
lock (xAxis)
{
if (xAxis[xIndex] == null)
xAxis[xIndex] = new Cluster[(int)worldSize.Y];
if (xAxis[xIndex][yIndex] == null)
xAxis[xIndex][yIndex] = new Cluster(this, new Vector2(xIndex * 256, yIndex * 256), worldLoader.loadClusterData(xIndex, yIndex));
}
}
loadCluster(int, int) 方法应确保在 getCluster(int, int) 方法检索集群之前将其加载到数组中,并且几乎始终如此,但偶尔 loadCluster(int, int) 会以某种方式无法添加集群。
这似乎不会发生在任何特定的集群上,但总是在没有添加内部数组时发生(但是,大多数情况下它会毫无问题地创建内部数组)。
此外,当 Visual Studio 捕获随后的空指针异常时,退后一步并重新调用 loadCluster(int, int) 始终(至少到目前为止)正常工作。在getCluster(int, int) 方法中添加对loadCluster(int, int) 的额外调用也大大降低了此错误的频率。
老实说,我不知道是什么导致这个相当简单的功能不起作用,甚至看起来是随机的。任何帮助将不胜感激
编辑:编辑 xAxis[][] 的其他代码
public override void Update(GameTime gameTime)
{
for (int x = 0; x < worldSize.X; x++)
{
if (xAxis[x] == null) continue;
int loaded = 0;
for (int y = 0; y < worldSize.Y; y++)
{
if (xAxis[x][y] == null)
{
continue;
}
xAxis[x][y].Update(gameTime);
if (xAxis[x][y].clusterLoaded)
{
loaded++;
}
else if (xAxis[x][y].clusterTimer == 0)
{
xAxis[x][y] = null;
}
}
if(loaded == 0) xAxis[x] = null;
}
}
Cluster.clusterLoaded 是一个布尔值,显示集群当前是否正在使用。
Cluster.clusterTimer 是一个 int,一旦 clusterLoaded 变为 false,它就会倒计时。如果clusterLoaded 再次变为真,则将其重置为最大值。每次运行 Cluster.Update(GameTime) 而 clusterLoaded 为 false 时,它会减 1。
loaded 用于统计当前内部数组加载了多少个Cluster。
【问题讨论】:
-
没有代码确保 (int)worldSize.Y > yIndex。请添加这样的断言,以便在这种情况下中断。
-
您能否发布所有更改数组的代码,包括从中删除的位 - 清理等?
-
很好发现,但到目前为止代码的其他部分确保 yIndex 永远不会大于 worldSize.Y。尽管无论如何我都会添加签到。在任何情况下,即使 xIndex 和 yIndex 在数组的范围内,也会发生错误。
标签: c# multithreading nullpointerexception jagged-arrays