So… I was working on the new Course, the « Fast Chunks – 8 – Infinite Chunks » and after testing a few things, i quickly noticed that it was absolutely not ready for infinite generation.
So i tried to start from scratch. I made a new version of the FastChunks project and tried to optimize a lot more. I took a few notes, trying new methods to get blocks in the world :
First i needed a better way to find a block in the world. I kept the old « GetChunk » method and used a few new things :
- Getting a local block :
Block world position – Chunk world Position (In this order)
- Getting a world block :
Block world position + Chunk world Position (In any order)
Then i put this into a new Method :
public static Block GetBlockInWorld(Vector3 _pos)
{
//The chunk containing the block
Chunk chunk = GetChunkAtPos(_pos);if (chunk == null) //If chunk doesn’t exist
return null;//Get the position of the chunk
Vector3 chunkPos = chunk.chunkObject.transform.position;//Convert block world to chunk local (Block pos – chunk pos)
Vector3 blockPosInChunk = _pos – chunkPos;//Get the block in the chunk (From the chunk map)
Block block = chunk.GetBlockAtPos((int)blockPosInChunk.x, (int)blockPosInChunk.y, (int)blockPosInChunk.z);//Give back the block
return block;
}
With this method i was able to simplify so much things! I don’t have to get a neighbour chunk and check if there is a block at a certain local position. Now i can just get the next block in the world. All i had to do was checking if it is null (If it exists) after searching for a block.
From this point i created a lot if useful methods, every one of them simplifies the scripts control :
public static Chunk GetChunkAtPos(Vector3 _pos) //Returns the chunk at the position
public static Vector3 GetChunkPos(Vector3 _pos) //We convert a position into a chunk position
public static Block GetBlockInWorld(Vector3 _pos) //We get any block in the world if it exists
public static bool BlockExistInWorld(Vector3 _pos) //Checks if a block exists at a position
public static void ResetChunk(Chunk _chunk) //We clear the chunk values, chunk object, and redraw
public static Vector3 GetMapLocationInChunk(Vector3 _blockPos, Chunk _chunk) //We get the position of a block inside the chunk map
public static Vector3 CenterPositionInBlock(Vector3 _pos) //When we click on a block, the position we are checking is centered inside the block
public static void RemoveBlockAtPos(Vector3 _pos) //Removes a block at the given position (If chunk exists)
public static void PlaceBlockAtPos(Block _block, Vector3 _pos) //Places a block at the given position (If chunk exists)
public static void CheckForNeighbours(Chunk _actualChunk, Vector3 _pos) //Checks if chunks around the position exists and resets them
public static Vector3 ConvertBlockPosToWorld(Chunk _chunk, Vector3 _blockPos) //Convert a block local position (Inside the chunk given chunk) into a world position
public static Vector3 ConvertBlockPosToChunkLocal(Chunk _chunk, Vector3 _blockPos) //Converts the block world position into a local position inside the given chunk
Then i tried to call the RemoveBlockAtPos method to create a new one, just for fun, it was called « BombAtPos ». Here are the results :
It loops around a position, at -1,-1,-1 to 1,1,1 and removes the block at each position if there is a block here.
public static void BombAtPos(Vector3 _pos)
{
//Loop all around the block
for (int x = -1; x <= 1; x++)
for (int y = -1; y <= 1; y++)
for (int z = -1; z <= 1; z++)
{
if (BlockExistInWorld(new Vector3(_pos.x + x, _pos.y + y, _pos.z + z))) //If block exists
RemoveBlockAtPos(new Vector3(_pos.x + x, _pos.y + y, _pos.z + z)); //Remove block at pos
}
}
It was really bad in big world because it checks neighbours around it. And there were a lot of chunks to check. So i had to remove some of them, that’s where Infinite generation comes in!
First, i had to generate chunks around the player. It was not that hard to do, it was just « If player last chunk is different than the actual player chunk position, we generate chunks around ». It looked good and worked fine :
So the next part was adding noise to test the chunk generation with it. I added Penny’s noise, the one i used in « Fast Chunks – 4 »
I also added the Concurrent dictionaries system. It avoids the out of sync dictionary when we read, draw and remove at the same time.
I also added chunks all around the player, using her « BuildRecursiveWorld » method. It generates a chunk, and chunk around it, and chunks around the new ones until we are out of the radius. These two additions gave me these results :
It started becoming slow but it was time to remove old chunks. And that’s where it stops working. Removing chunks means accessing the chunks list again and all i was doing was looking in the Dictionary, all the time.
So it was even more slow, and i knew i had to find a new solution.
It tried to generate chunks columns, it was also slow.
The last solution i have for now, that i still have to try, is to virtualize a lot more. Don’t draw the sides of chunks, don’t draw anything that is not visible, and add occlusion to hide chunks behind the player. I have to minimize the drawn chunks and blocks, minimize the chunks in the list with bigger but optimized chunks.