At this point I actually think the delay we “see” is when we’re adding the chunks to the scene frame after frame. So we’re running at hundreds of frames per second and nothing is happening, happy clappy, then we move out of a chunk and for 14 frames (assuming a 3x3 - 7 chunks removed, 7 chunks added) something is going on. These actions result in a slight loss of frame speed, and it is conveyed to the user as a kind of lag spike. You can counter this by enabling vsync or using a fixed frame rate. If we threw everything into one frame (instead of spreading it out over multiple frames), it would only make the projected visualization worse.
We can lessen this behaviour by reducing the load required to add and remove chunks, but lets see exactly are we doing here and what we can do.
We return true if work was carried out, else false.
for every frame…
> Check for chunks outside our view distance and remove them by:
- Iterating through the worldTiles (loaded tiles) hashmap
- if any of these tiles are lessThan or greaterThan our viewdistance, iterator.remove();
- return true if we removed a tile, else return false.
> Check for new chunks inside our view distance by:
> check the worldTiles.size() to see if it matches the total tiles (e.g. 7x7 = 49 tiles) and return false if the size is what we expect for a fully loaded scene.
> .poll() a ConcurrentLinkedQueue to see if any loaded tiles are in the que and ready to add. Add it and return true if .poll() != null.
> iterate over our view distance.
> check the worldTiles (that contains our loaded tiles) hashmap using .get(); to see if this tile is loaded. if found, continue;
> check the cache hashset using .contains();
> if found in the cache, add it to the scene, add it to the loaded tiles, return true;
> if not found, create a new runnable to load the tile, and return true
> nothing happened, so return false
Not a great deal of work is being done here. Worst case frame, we iterate over 49 items (assuming a viewdistance of 3 in all directions plus the center chunk), issue a .get() on a hashmap, issue a .contains() on a hashset and fire a runnable into the threadpool.
At this point in time, i’m all out of ideas on condensing that logic.