0 votes

How can we make a node globally acessable to other nodes in stabilished trees?

Say I have a camera inside my player node, and I have a fog texture in a canvas node, which it's shader will use the camera position to offset the UV. How do I make the camera globally acessable? I am familiar with autoloads, but I can't get it to work properly, my intention is to make a standard structure of nodes for my game maps, like:

MAP_001_The_Gargatua:
    DYNAMIC:
        LIGHTS
        OBJECTS
        ENTITIES:
            ENEMY_001
            PLAYER
                MAIN_ACTIVE_CAMERA
        MOVEABLES
        ITEMS
    STATIC:
        TILESETS
    POST_PROCESS_CANVAS:
        FOG
        VEINS_FX
        BLOOD_FX

Then some objects could store their reference in a global node, then they could be called from any other node in the map. My current situation is the FOG texture shader trying to access the camera inside the player. I would do currently a lot of get_parent() or get_tree().

My project is getting bigger, and so far have been doing direct referencing like get_node() or $ pathing, which I know, isn't the best approach, my get_parent() get_tree() get_node() codes are looking like a noodle soup, no pun intended, it's all over the place.

Sometimes I can bypass this using the dinamic design approach, wherer B doesn't need to know A to do X. I do this using classes and pre-determined common variables like OBJECT_TYPE:Door, or using the collision layers, or using other methods like filtering by NODE type, but sometimes we need to reference a specific object like the Player.

So how can I store the path of a node or the node itself in a global access point? Or my approach with this situation is wrong?

in Engine by (369 points)

2 Answers

+1 vote

Firstly, to get the main camera of the scene you can simply access it from Viewport.get_camera(), while main viewport can also be accessed with Node.get_viewport():

var main_camera = get_viewport().get_camera()

For accessing other node globally, it is recommended to use group:

# Retrieve all nodes under "player" group
var players = get_tree().get_nodes_in_group("player")
by (216 points)

Oops, didn't metioned it was a 2D camera, my bad, but sadly, the get_viewport() line retrieves only the 3D camera as it is currently. Somebody opened a discussion about that somewhere...

It's ok, at least I learn something new, didn't know that before

+2 votes

What I do is "registering" it to a global script.
IDK if it's good advice.
With an autoloaded global script I can:
var player
And in the player script's _ready:
global.player = self
and after that everyone can access player with global.player
Only thing is that you better not access it from _ready, because it may not be there in time. You can use call_deferred().
Grouping is the way to go for enemies (there is more than one enemy) and it may be better for other nodes too.

by (288 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.