patterncsharpModerate
Chunk Generation Performance in C#
Viewed 0 times
chunkgenerationperformance
Problem
I'm working on a game in C#, this game generate new chunk (infinite) when you move around. If I have > 1000 chunks in my list then it become laggy even though I only load the necessary chunks on my screen. Tried all things to improve the code but it did not improve.
```
Stopwatch ChunkDetect = new Stopwatch();
List allChunks = new List();
public readonly int sizeChunk = 800;
private void loadChunks()
{
ChunkDetect.Restart();
ChunkDetect.Start();
int CamXCh = Convert.ToInt32(Math.Ceiling(-Convert.ToDouble(CameraX) / sizeChunk)),
CamYCh = Convert.ToInt32(Math.Ceiling(-Convert.ToDouble(CameraY) / sizeChunk));
int sizeX = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(gameBox.Width) / sizeChunk)) + 4,
sizeY = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(gameBox.Height) / sizeChunk)) + 4;
Random generation = new Random();
// Load Chunks or Create
for (int chunkX = 0; chunkX i.positionX == xChunk && i.positionY == yChunk).FirstOrDefault();
bool isLoad = true;
if (chunkX == 0 || chunkX == (sizeX - 1) || chunkY == 0 || chunkY == (sizeY - 1))
isLoad = false;
if (currentChunk == null)
{
Color ColorBiome = Color.FromArgb(64, 233, 56);
string BiomeName = "Grass";
allChunks.Add(new Chunks(xChunk, yChunk, sizeChunk, ColorBiome, BiomeName, isLoad, 40));
}
else
{
bool isCurrentLoaded = currentChunk.isLoaded;
if (!isLoad)
currentChunk.isLoaded = false;
else if (!isCurrentLoaded)
currentChunk.isLoaded = true;
}
}
}
ChunkDetect.Stop();
}
class Chunks
{
public Color biomeType;
public Guid uid;
public bool isLoaded;
public int positionX, positionY, Size;
public string biomeName;
public List MapChunk;
public Chunks(int x, int y, int size, Color biom
```
Stopwatch ChunkDetect = new Stopwatch();
List allChunks = new List();
public readonly int sizeChunk = 800;
private void loadChunks()
{
ChunkDetect.Restart();
ChunkDetect.Start();
int CamXCh = Convert.ToInt32(Math.Ceiling(-Convert.ToDouble(CameraX) / sizeChunk)),
CamYCh = Convert.ToInt32(Math.Ceiling(-Convert.ToDouble(CameraY) / sizeChunk));
int sizeX = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(gameBox.Width) / sizeChunk)) + 4,
sizeY = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(gameBox.Height) / sizeChunk)) + 4;
Random generation = new Random();
// Load Chunks or Create
for (int chunkX = 0; chunkX i.positionX == xChunk && i.positionY == yChunk).FirstOrDefault();
bool isLoad = true;
if (chunkX == 0 || chunkX == (sizeX - 1) || chunkY == 0 || chunkY == (sizeY - 1))
isLoad = false;
if (currentChunk == null)
{
Color ColorBiome = Color.FromArgb(64, 233, 56);
string BiomeName = "Grass";
allChunks.Add(new Chunks(xChunk, yChunk, sizeChunk, ColorBiome, BiomeName, isLoad, 40));
}
else
{
bool isCurrentLoaded = currentChunk.isLoaded;
if (!isLoad)
currentChunk.isLoaded = false;
else if (!isCurrentLoaded)
currentChunk.isLoaded = true;
}
}
}
ChunkDetect.Stop();
}
class Chunks
{
public Color biomeType;
public Guid uid;
public bool isLoaded;
public int positionX, positionY, Size;
public string biomeName;
public List MapChunk;
public Chunks(int x, int y, int size, Color biom
Solution
Your
The solution is to index the chunks in a way that makes the lookup performance a constant-time operation (not dependant on the number of chunks).
The logical data structure for this is to use a Dictionary, and key the Dictionary on a value that is the coordinate. Thus, given a coordinate, you can easily find the Chunk.
Your chunks are indexed using int values for the X and Y coordinate. I would recommend using a long-value as the key, and to simply shift the X and Y coordinates in to the Dictionary... for example:
The Dictionary will convert the lookup process to a faster, scalable mechanism.
If you want to, you can create a more complicated key mechanism, but I would recommend that you keep the key as simple as possible.
allChunks is a List. The Linq query to get the chunk with the right coordinates is going to scan the entire list, and check each chunk. This is a linear process, and the performance depends on the number of chunks in the list. As the list grows, the performance decreases.The solution is to index the chunks in a way that makes the lookup performance a constant-time operation (not dependant on the number of chunks).
The logical data structure for this is to use a Dictionary, and key the Dictionary on a value that is the coordinate. Thus, given a coordinate, you can easily find the Chunk.
Your chunks are indexed using int values for the X and Y coordinate. I would recommend using a long-value as the key, and to simply shift the X and Y coordinates in to the Dictionary... for example:
Dictionary indexChunks = ....
// merge both coordinates in to one unique key
// the y-coordinate is in the high-32-bits, the x-coord in the low 32 bits.
// this should probably be in a function.
long key = xChunk + ((long)yChunk << 32);
if (!indexChunks.containsKey(key)) {
indexChunks.Add(key, new Chunks(.....));
}
Chunks currentChunk = indexChunks[key];The Dictionary will convert the lookup process to a faster, scalable mechanism.
If you want to, you can create a more complicated key mechanism, but I would recommend that you keep the key as simple as possible.
Code Snippets
Dictionary<long, Chunks> indexChunks = ....
// merge both coordinates in to one unique key
// the y-coordinate is in the high-32-bits, the x-coord in the low 32 bits.
// this should probably be in a function.
long key = xChunk + ((long)yChunk << 32);
if (!indexChunks.containsKey(key)) {
indexChunks.Add(key, new Chunks(.....));
}
Chunks currentChunk = indexChunks[key];Context
StackExchange Code Review Q#55020, answer score: 10
Revisions (0)
No revisions yet.