get_tree() best practices

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By tsalexey544

I am confused when get_tree() should be used and what are the best practices for using get_tree().

Can it be used instead of
@onready var camera = $"/root/World/Camera2D"

:bust_in_silhouette: Reply From: popcar2

You should still use $ when getting variables in your tree. get_tree() gives you the SceneTree, which is used when you want to access methods or properties stored in it, such as wanting to change the scene (get_tree().change_scene_to_packed) or getting all nodes in a group (get_tree().get_nodes_in_group), among other things.

You can see what it can do in the docs: https://docs.godotengine.org/en/stable/classes/class_scenetree.html

Thanks, but how will it look? Like this?

@onready var camera = get_tree().$"/World/Camera2D"

tsalexey544 | 2023-04-14 13:33

No, just do @onready var camera = $"/root/World/Camera2D". Don’t do get_tree() unless you specifically want something from it.

popcar2 | 2023-04-14 13:37

:bust_in_silhouette: Reply From: eons

Avoid using absolute paths, there is where get_tree() is used.

So in your case, use get_tree().current_scene.get_node("Camera2D").

Even better, if you use unique nodes, the Camera2D node can be anywhere in the current scene, so you do:
get_tree().current_scene.get_node("%Camera2D")

As long as the current scene is expected to have a unique node named Camera2D, that code will work no matter the names of the rest of the nodes and the location of the camera (in the current scene).

:bust_in_silhouette: Reply From: stormreaver

I always pass the camera object from scene to scene, which eliminates the need to know the full path for the camera. It then always becomes a local reference, which is easy to manage, rather than a global one.

Can you show an example?

tsalexey544 | 2023-04-17 18:44

Here’s a sample sequence from a VR game using Godot 3.5. From my main scene (shortened to show just the relevant bits). Note that there are two camera references One reference is to the camera that is used to track user positioning, and the other camera is used to track user orientation:

func _ready():
	setControllers()
	createIntroductionScene()

func setControllers():
	m_cameraPosition = $ARVROrigin
	m_cameraOrientation = $ARVROrigin/Camera

func createIntroductionScene():
	m_game = load("res://scenes/introduction/Introduction.tscn").instance()
	add_child(m_game)
	m_game.setCameraPosition(m_cameraPosition)
	m_game.setCameraOrientation(m_cameraOrientation)

Then in the Introduction scene:

var m_cameraPosition
var m_cameraOrientation

func setCameraPosition(a):
	m_cameraPosition = a
	m_player.setCameraPosition(a)
	
func setCameraOrientation(a):
	m_cameraOrientation = a
	m_player.setCameraOrientation(a)

Now if something in the Introduction scene needs to interact with the camera, the reference is right there without having to worry about where the camera is in the grand scheme of scenes. It also keeps its reference if the camera is reparented:

var pntWhere = m_cameraPosition.global_transform.origin

stormreaver | 2023-04-18 11:48

Thanks for the help

tsalexey544 | 2023-04-18 12:09