I've actually moved away from detecting neighboring rooms. The decision was partially accidental: I was already wondering how useful it actually was, when I had everything working and went back to the code and noticed I had forgotten to uncomment a crucial portion of the code - and it was still working as I intended it to!
In fact, my rooms are now merely an Area2D to detect entering/exiting bodies, a Polygon2D for two types of fog-of-war, and a raycast next to each doorway. Doors are also just doors now.
On one hand, it was being a pain to be setting up many rooms in a map (and to be honest, it still kind of is, but it's much better now), and keeping their content properly organized within their hierarchical structure. On the other hand, I ended up coming to the conclusion that stuff like lights and enemies need a more personalized way to deal with. Lights are now in their own independent node "Lights" (in the map structure, not rooms), so it's easy to place them around the map. They were already independent in terms of detecting how far the player is, and getting turned on and off, so, this seemed only natural.
(I'm trying to make a stealth game, by the way, which is why lights have their own simple scripting, which gets processed if the player is within range. They give the player the level of brightness he's in.)
As for the enemies and other entities, I'm considering doing the same thing. I may use the rooms' Area2Ds to detect what is in the rooms at the start, and add them as children through code. I'm still undecided on that, but in terms of map making, I found it way easier to just separate things.
I'm using plenty of raycasts though, but they don't seem to weigh on performance. I created a scene called Seeker and wrote my own sort-of-abstraction for them to make using them easier. I use them with a cast_once() function, which forces a raycast update, unless I'm debugging in which case I actually enable/disable them. (I could probably do that with just a script and no scene, but I'll tackle that later on.)
The lights and enemies have one each, and rooms have one per door, all of them to detect whether the player is visible to them. If he is, the light affects his visibility, the enemy spots him, the room hides the fog-of-war, vice-versa, etc.
Now, I'm deactivating stuff based on whether they're off the screen (based on distance to the player, screen size and camera zoom), because my previous intention of deactivating rooms and their content based on neighborhood queries actually made it look awkward. Lights would turn off instead of staying lit under the fog-of-war, pouring into other rooms from under it, for example.
I wonder though, whether deactivating stuff that's off screen is redundant (with hide()
).
I also tackled with using a mask to create a proper fog-of-war-ish player's field of view, and I like how it looks, except then the walls go totally black. I tried switching layers around but couldn't get them to show up...