I wanted to share a Resource and Inspector plugin I recently released called SceneNodePath.
Originally, I just needed a UI in the inspector that would let me pick specific nodes from external .tscn files, essentially bringing the convenience of a local NodePath to external scenes.
While putting it together, I realized I could use UIDs under the hood to make these references reliable. So now, if you move the target scene file or rename things, the reference doesn’t break. That rabbit hole eventually led me to build a more ergonomic wrapper around Godot’s SceneState API as well. Basically**:**
Gives you a custom node picker dialog in the Inspector to browse external scene hierarchies.
Uses UIDs so your external node references survive file movements.
Lets you query an external node’s properties, groups, and types without having to instantiate the massive scene into memory first.
Fully supports both GDScript and C#.
I spent some time polishing the in-godot documentation to make it easy to drop into existing projects.
I wouldn’t want to dimish the project - seems like you put a lot of work into it. However, this approach seems like an anti-pattern by breaking the encapsulation, wouldn’t you agree?
In your example of accessing a SpawnPoint inside the Level - I’d argue that the spawn_point should be an exposed property of the Level class and you assign its value to be the SpawnPoint node. Then outside of the Level class scope you don’t need to access the SpawnPoint node directly, you just reference the Level::spawn_point property.
Help me understand how your project solves this better.
That’s a fair point, and honestly I hadn’t thought about scene children as private vs public in that way before. You’re right that exposing a spawn_point property on the Level class is cleaner encapsulation.
That said, I think Godot itself doesn’t really enforce that boundary. There’s no way to mark children as private or public, and in practice, most people reach into scenes with get_node_or_null("%CombatComponent") all the time. If you have characters with different optional components, the “proper” way would be to create a class API for each combination, but I would guess almost nobody does that. Everyone just duck-types their way through the tree. I think if Godot had something like traits or interfaces this would be less of an issue.
So I’d say whether this is an anti-pattern depends on the project. For my use case, I have a multiplayer addon with a lobby system where players can teleport between replicated scenes. Any scene with a MultiplayerSpawner rooted correctly can be a lobby “world.” I use SceneNodePath to let users pick which scenes go into the auto-spawn list from the Inspector. I also have a teleportation setup between lobbies, and each teleporter needs a reference to both a destination scene and a specific Marker2D inside it, SceneNodePath handles that wiring cleanly without code.
So it’s less about replacing good scene APIs and more about editor-driven cross-scene references where you’re pointing at specific nodes across scene boundaries.