HashSets and Tilemaps
If you're working with Tilemaps, get familiar with HashSet.
A HashSet can be thought of as just the key part of a Dictionary. Many times, if you're working with Tilemaps, you load a scene and you want to scan the tilemaps and look for static (non-moving) obstacles. You don't care what's in that position, but you know that these positions are off-limits to characters and/or NPCs in your game.
Here's an example of some code that can be used to load a HashSet with all the occupied positions on a Tilemap:
public HashSet<Vector3Int> GetAllPositionsForMap(Tilemap map)
{
if (map == null)
return null;
HashSet<Vector3Int> output = new HashSet<Vector3Int>();
//make the map a little easier to deal with by compressing the bounds.
map.CompressBounds();
var bounds = map.cellBounds;
//get the block of tiles within the bounds
var block = map.GetTilesBlock(bounds);
var width = bounds.size.x;
var height = bounds.size.y;
//loop thru the block
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
var pTile = block[x + (y * width)]; //any tile here?
//might be nothing at that position
if (pTile == null)
continue; //no
//compute proper position relative to bounds
var pos = new Vector3Int(x + bounds.xMin, y + bounds.yMin, 0);
output.Add(pos); //note that hashset ignores duplicates
}
}
return output;
}
HashSets are amazing when you just need to know if something exists. If you examine your code you may find places where you're using a dictionary but really only need the keys most of the time.
Tip: for Dictionaries and HashSets the simpler the key the faster the key lookup becomes. For example, if you wanted to make a Dictionary that maps Tilemaps as Keys and strings as values you would declare it as
Dictionary <Tilemap, string> m_TilemapToStringDictionary;
but since Tilemaps are Unity objects, you can use the Tilemap's instance ID as the key instead:
Dictionary<int,string> m_TilemapToStringDictionary.