There's not much to see, really. The monsters are added through a slightly complicated chain of events as children of the dungeon, which inherits from TileMap. So, when I want to check a particular grid location I do
func map_unit(pos:Vector2):
for c in get_monsters():
if c.grid_position == pos:
return c
func get_monsters():
var out = []
for c in get_children():
if c.get('is_creature'):
out.append(c)
return out
That's a simplified version.
The advantage for me is that I don't have to maintain the objects in two places. They're always going to be part of the scene tree, so if I use another structure to track them, I'm duplicating effort, and creating the possibility of the two getting out of sync (which actually happened when I was doing it that way).
Note that I'm checking for an "is_creature" property instead of using "is Creature" to check the object type. That's just because gdscript 1.x still has huge issues with cyclic references. In a project with a lot of code, it becomes impossible to use typed variables with custom class names or even to use the "is" keyword without errors.
I just offer that as an alternative. There are lots of ways to do it.