我正在尝试在 C# 中生成体素,但有一个奇怪的错误。
我已经用 C# 生成了其他体素,但从未遇到过这个错误;
看起来像这样:
######
####
####
#
#
#
[有关图片,请参阅 reddit 上的帖子。]
我尝试了多种方法,但只有一种方法有效,在每一代之间等待一帧。
加载块数组的代码:
public void Update(float state)
{
if (chunkQueue.Any()) chunkService.LoadChunk(chunkQueue.Dequeue());
var cameraPosition = cameraSet.GetEntities()[0].Get<Transform>().Position;
var cameraChunkPosition = new Vector2Int
{
X = (int)Math.Floor(cameraPosition.X / 16),
Y = (int)Math.Floor(cameraPosition.Z / 16)
};
for (int x = 0; x < renderDistance; x++)
{
for (int z = 0; z < renderDistance; z++)
{
var chunkPosition = cameraChunkPosition +
new Vector2Int(x - halfRenderDistance, z - halfRenderDistance);
if (existingChunk.Contains(chunkPosition)) continue;
chunkService.LoadChunk(chunkPosition);
// chunkQueue.Enqueue(chunkPosition);
existingChunk.Add(chunkPosition);
}
}
}
但是如果我取消注释 //chunkQueue.Enqueue(chunkPosition);
并注释 chunkService.LoadChunk(chunkPosition);
正确生成如下:
######
######
######
######
######
######
[有关图片,请参阅 reddit 上的帖子。]
为什么会发生这种情况?
我猜是记忆有问题还是什么的。
块生成发生在这个文件中:
using DefaultEcs;
using Flux.Core.Rendering;
using Flux.Core.ServiceAbstraction;
using Flux.Core.Services;
namespace MinecraftClone;
class ChunkService
{
readonly IEcsService ecsService;
readonly GL gl;
readonly TerrainService terrainService;
readonly Shader globalShader;
public ChunkService(IEcsService ecsService, GL gl, ResourcesService resourcesService, TerrainService terrainService)
{
this.ecsService = ecsService;
this.gl = gl;
this.terrainService = terrainService;
globalShader = resourcesService.LoadShader("Chunk.vert", "Chunk.frag");
}
public Entity LoadChunk(Vector2Int chunkPosition)
{
var blocks = GenerateChunkData(chunkPosition, terrainService);
var vertexs = new List<float>(16 * 16 * 16 * 6);
var faces = new List<uint[]>();
for (int x = 0; x < ChunkMath.ChunkSize; x++)
{
for (int y = 0; y < ChunkMath.ChunkSize; y++)
{
for (int z = 0; z < ChunkMath.ChunkSize; z++)
{
var isFull = blocks[x, y, z];
if (!isFull)
continue;
var blockPosition = new Vector3Int(x, y, z);
vertexs.AddRange(BlockData.OffsetFace(BlockData.XFaceVertex, blockPosition));
faces.Add(BlockData.XFaceIndice);
vertexs.AddRange(BlockData.OffsetFace(BlockData.NegXFaceVertex, blockPosition));
faces.Add(BlockData.NegXFaceIndice);
vertexs.AddRange(BlockData.OffsetFace(BlockData.YFaceVertex, blockPosition));
faces.Add(BlockData.YFaceIndice);
vertexs.AddRange(BlockData.OffsetFace(BlockData.NegYFaceVertex, blockPosition));
faces.Add(BlockData.NegYFaceIndice);
vertexs.AddRange(BlockData.OffsetFace(BlockData.ZFaceVertex, blockPosition));
faces.Add(BlockData.ZFaceIndice);
vertexs.AddRange(BlockData.OffsetFace(BlockData.NegZFaceVertex, blockPosition));
faces.Add(BlockData.NegZFaceIndice);
}
}
}
var indexes = ComputeIndexes(faces);
var entity = ecsService.World.CreateEntity();
entity.Set(chunkPosition);
entity.Set(new Chunk(gl, globalShader, vertexs.ToArray(), indexes));
return entity;
}
private static uint[] ComputeIndexes(List<uint[]> faces)
{
var indices = new uint[faces.Count * 6];
for (int i = 0; i < faces.Count; i++)
{
var face = faces[i];
uint indiceOffset = (uint)i * 6;
uint vertexOffset = (uint)i * 4;
for (int ii = 0; ii < 6; ii++)
{
indices[indiceOffset + ii] = face[ii] + vertexOffset;
}
}
return indices;
}
static bool[,,] GenerateChunkData(Vector2Int chunkPosition, TerrainService terrainService)
{
var blocks = new bool[ChunkMath.ChunkSize, ChunkMath.ChunkSize, ChunkMath.ChunkSize];
for (int x = 0; x < ChunkMath.ChunkSize; x++)
{
for (int y = 0; y < ChunkMath.ChunkSize; y++)
{
for (int z = 0; z < ChunkMath.ChunkSize; z++)
{
var blockX = x + (chunkPosition.X * ChunkMath.ChunkSize);
var blockZ = z + (chunkPosition.Y * ChunkMath.ChunkSize);
var isFull = y < terrainService.GetHeight(blockX, blockZ, 16);
blocks[x, y, z] = isFull;
}
}
}
return blocks;
}
}