Question by
ByBarxX · Mar 31, 2021 at 02:39 PM ·
procedural meshthreading
Procedural generation (Minecraft Like) with unity jobs problem
I'm trying to make a procedural minecraft-style generation, but if I increase the chunk size to 16x5x16 the lag increases a lot and I don't know what more of the code I could optimize.
This is the job code:
public struct BuildChunkJob : IJob
{
public byte chunkSize,chunkHeight;
public Vector3Int chunkPosition;
public BlockUtils utils;
public void Execute()
{
var chunkData = new Block[chunkSize, chunkHeight, chunkSize];
var chunk = new Chunk(chunkPosition, 0, false, false);
for (var cZ = 0; cZ < chunkSize; cZ++)
{
for (var cY = 0; cY < chunkHeight; cY++)
{
for (var cX = 0; cX < chunkSize; cX++)
{
var pos = new Vector3Int(cX, cY, cZ);
var worldX = cX + chunk.chunkPos.x;
var worldY = cY + chunk.chunkPos.y;
var worldZ = cZ + chunk.chunkPos.z;
var surfaceHeight = World.instance.utils.GenerateHeight(worldX, worldZ);
byte id = 0;
var isOpaque = false;
if (worldY < surfaceHeight || worldY > surfaceHeight)
{
chunkData[cX, cY, cZ] = new Block(pos, chunk.chunkPos, 0, false);
continue;
}
if (worldY == surfaceHeight)
{
id = 2;
isOpaque = true;
chunk.opaqueFull = true;
}
else if (worldY == World.instance.utils.waterLevel)
{
id = 5;
chunk.transparentFull = true;
}
chunkData[cX, cY, cZ] = new Block(pos, chunk.chunkPos, id, isOpaque);
}
}
}
if (!chunk.opaqueFull && !chunk.transparentFull) return;
foreach (var cd in chunkData)
{
var position = cd.position;
if (cd.id == 0) continue;
if (!utils.HasSolidNeighbour(position.x, position.y + 1, position.z, cd, chunkData))
utils.CreateQuad(1, position, cd.id);
if (cd.id == 5) continue;
if (!utils.HasSolidNeighbour(position.x, position.y - 1, position.z, cd, chunkData))
utils.CreateQuad(0, position, cd.id);
if (!utils.HasSolidNeighbour(position.x, position.y, position.z + 1, cd, chunkData))
utils.CreateQuad(4, position, cd.id);
if (!utils.HasSolidNeighbour(position.x, position.y, position.z - 1, cd, chunkData))
utils.CreateQuad(5, position, cd.id);
if (!utils.HasSolidNeighbour(position.x - 1, position.y, position.z, cd, chunkData))
utils.CreateQuad(2, position, cd.id);
if (!utils.HasSolidNeighbour(position.x + 1, position.y, position.z, cd, chunkData))
utils.CreateQuad(3, position, cd.id);
}
World.instance.chunks.Add(WorldUtils.BuildChunkName(chunkPosition), chunk);
World.instance.chunksBlockData.Add(chunk, chunkData);
}
}
And the main thread:
private IEnumerator BuildWorld()
{
player.UpdatePlayerChunkPos();
var playerChunkPos = player.chunkPos;
foreach (var chunkPos in from t in _viewDistancePositions where t.y * chunkHeight + playerChunkPos.y >= 0 select new Vector3Int(t.x * chunkSize, t.y * chunkHeight, t.z * chunkSize) + playerChunkPos)
{
if (chunks.ContainsKey(WorldUtils.BuildChunkName(chunkPos))) continue;
var job = new BuildChunkJob()
{
utils = blockUtils,
chunkHeight = chunkHeight,
chunkSize = chunkSize,
chunkPosition = chunkPos,
};
var handle = job.Schedule();
handle.Complete();
if (!chunks.TryGetValue(WorldUtils.BuildChunkName(chunkPos), out var c)) continue;
if (c.state != 0) continue;
if (c.opaqueFull)
ChunkUtils.CreateMesh(ChunkUtils.CreateObject(WorldUtils.BuildChunkName(chunkPos), chunkPos, chunkPrefab), mats[0],
true);
if (c.transparentFull)
ChunkUtils.CreateMesh(ChunkUtils.CreateObject($"{WorldUtils.BuildChunkName(chunkPos)}_T", chunkPos, chunkPrefab),
mats[1], false);
quadsToDrawOpaque.Clear();
quadsToDrawTransparent.Clear();
c.state = 1;
yield return new WaitForEndOfFrame();
}
}
Comment