2D Procedural Terrain Generation + Pooling

I am in the process of trying to create a game similar to Terraria or Starbound. I have been trying out different methods of optimizing map creation over the last week. Somebody in the forums stated to me they could create a 4096 x 4096 map that only uses 128 MB memory total (according to Unity profiler) by using pooling.

Pooling is a new concept to me, and I have done some reading and checking out some tutorials on it. I think…I understand how it could be used, but the second I tried to use it I wound up with a 384 x 384 map that uses 750 MB memory and takes 30 seconds to load. So I obviously must be doing something wrong, because so far pooling appears to be crap.

Here is what I have done. I have 3 prefabs, Map, Chunk, and Tile. The tile prefab is a GameObject with a SpriteRenderer and Box Collider 2D. The chunk is an empty game object meant to serve as a parent to the tiles it contains (for organizational purposes). It contains a script that includes tile width, tile height, and a 2D tile array. On load, it initializes the tile array and instantiates all tiles it contains. Finally, the Map is an empty gameobject that holds chunks. It has a script attached that includes max chunks to create. On load it instantiates chunks up to its max (which in turn causes the chunks to instantiate their tiles).

The goal is that there will be a chunk above, below, left, right, upper left, upper right, lower left, lower right, of the player, including the chunk the player is in. As the player heads in a direction, the chunk gets moved to be ahead of the player. So I will never need more than 9 loaded at a time (unless I go multiplayer), and the player should in theory, be able to move in any direction endlessly.

What values the tiles on the map have (i.e. air, dirt, etc. and other info) is dictated by a MapData script. When the chunks move, the tiles within the moved chunk set themselves based on the MapData of the tile located at its position.

So that’s my theory. Can anybody tell me where I might be misunderstanding the concept, or misusing it in any way? When the game releases, I want a load time of 1 minute or less for a computer that meets the minimum requirements. So having a map that takes 30 seconds to generate (without grass, trees, physics, enemies, npcs, etc.) on a beast computer is unacceptable.

Check out this website: Student Game Dev has moved!: Unity Voxel Tutorial Part 1: Generating meshes from code
You can adapt this to 2d I made it, and it works pretty good. The only catch is that you’ll need to create your own outline in a Polygon Collider. I you manage to do this then tell me haha

Actually going to answer my own question here since I managed to resolve the issue myself. Thanks to everybody who tried to help though. The solution to the problem was actually fairly straight forward.

I attach a rigid body 2d to my player and draw large 2d box colliders around every chunk in the map. When the map is generated, each chunk is created, although the blocks within are not(but the block data is). When the player’s rigidbody enters a chunk trigger zone, the chunk will flag itself as a player containing chunk while the player remains within its confines. The player can be in as little as 1 chunk and as many as 4 chunks at once if they are standing on 4 corners.

Then at pre-defined intervals (for me it is every 1 second), my BlockPool script will poll all the chunks and add those chunks that contain the player to a list. The pool will also add the chunks surrounding all player chunks to the list as well, to act as a chunk buffer so the player never sees loading chunks. Then I take the old player chunks including buffer and remove any chunks that are not currently player chunks or buffer chunks.

Finally, the BlockPool will call two separate coroutines to run over time within the chunks, one tells garbage chunks to destroy its blocks, the other tells active chunks to create their blocks. When playtesting in Unity, as the player moves in one direction you will see chunks being created in front and around them as they move, while the chunks that are left behind are destroyed. Its quite a pretty sight.

Final statistics on map generation:

Large: 8192 x 2048 blocks Memory Used: 65 MB FPS: 60+

Small: 4096 x 1024 blocks Memory Used: 50 MB FPS: 60+

Chunk Size used: 32 x 32 blocks

Block Size used: 24 x 24 px

So as you can see, it is very thorough and there are no FPS spikes either. Hope this answer helps somebody else delving into this in the future!