How would you get a node's position from another scene

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

I would like to get the global_position of a node Player in my Main.tscn and i would like to access it from another scene Projectile.tscn but this code dosen’t work

extends KinematicBody2D

  onready var player = get_tree().get_root().get_parent().get_node("Player")
  var target = null

func _physics_process(delta): 

    target = player.position
    print(target)

Hi
are you sure that the player node is already in the tree? When this onready event fires the player maybe not ready yet.

klaas | 2021-09-21 17:09

The player node is a node in my Main.tscn idk if its in the tree

I have tried using:

extends KinematicBody 2D

  var player = get_node("/root/Main.tscn/Player"), and
  var player = get_tree().get_root().get_node("Main.tscn/Player")

javrocks | 2021-09-21 17:11

try this

 get_tree().get_root().find_node().find_node("player",true,false)

but you have to be sure that the player has entered the tree before

klaas | 2021-09-21 17:22

It says theres is Too few arguments for “find_node()” call. Expected at least 1.

javrocks | 2021-09-21 17:34

but there are 3 arguments “player”, true and false

klaas | 2021-09-21 17:37

to clearify
a included scene is not found under its .tscn name.

try

 get_tree().get_root().print_tree_pretty()

to have a look into your actual tree structure

klaas | 2021-09-21 17:43

Idk why

How would you get a nodes position from another scene
Or how would you add the player node to the tree

javrocks | 2021-09-21 17:44

when it prints it seems normal to me

javrocks | 2021-09-21 17:49

you could put the player in a group and get the group members

Groups — Godot Engine (latest) documentation in English

this would be easier than getting the object directly

klaas | 2021-09-21 17:49

I tried that and put the player node in a group called “Player” but it said it cant get the nodes position because it an array

I used onready var player = get_node(“res://Main.tscn”).get_nodes_in_group(“Player”)

javrocks | 2021-09-21 17:51

i highly recomend to read through some tutorials first … i think you missed some key concepts in godot …

this is a good start in terms of node paths

https://kidscancode.org/godot_recipes/basics/getting_nodes/

klaas | 2021-09-21 18:30

Have you ever done this in godot before?

javrocks | 2021-09-21 18:43

:bust_in_silhouette: Reply From: javrocks

I Found A Method that Works:

extends Area2D

onready var player := get_tree().get_root().get_node("Main2D").get_node("Player")

func _ready():
   print(player)  

This method get’s the node “Player” via its parent “Main2D” and prints it

:bust_in_silhouette: Reply From: Inces

Man, this is a mess :slight_smile:
You should GIVE the players position to the scene that depends on it, not force it to obtain this information by itself. Your scene should contain some menager node, with player as its child, and when it would create projectiles, it would know players position as a parent, and would give it to projectiles. Another way is to menage those thing with signals, for example every time player presses shoot button, it emits signal with his current position and direction, so another node can create bullets from those information

If you were to use a signal to send the players position how would the projectile
receive it in another scene

How do you send a signal across a scene??

javrocks | 2021-09-23 22:40

Function emit_signal(variant) always emits across the scenes, as long as they all belong in one Scene tree. It is best to use Autoload and call it to emit signal. Every node who is interested in this signal, will have to use function connect() in its ready function. Finally interested node will have its own function for reacting on this signal.

Tell me what do you want to do in your game with this player, position and projectile, and I will show You how You should structure signalling code.

Inces | 2021-09-26 07:02

I don’t know if it is possible to store the players position in a signal but i would like the player to emit a signal containing its global position and the in my Enemy scene i would like to connect to that signal and use the player position as a target for the enemies

javrocks | 2021-09-26 13:15

:bust_in_silhouette: Reply From: DaddyMonster

Ok, so what you really want to do it pass a reference of one sibling object to another.

Your approach of trying to directly reference the object in the tree is very brittle, objects and scenes can be added and removed from the tree at any time which will break the hard reference in the code. My personal rule of thumb is only to use hard references within scenes and even then to have a Path set in the editor; so if you rearrange nodes it won’t break. Even if it does break, if the problem is within a single scene, ironing out the references generally isn’t hard.

The simplest/laziest/dirtiest approach between scenes is just to have a singleton with a variable/array/dictionary. Then when you make the target it can add itself to the list in the ready method - eg singleton.target.append(self) - and when it dies it can remove itself. Global variables like this are frowned upon by seasoned coders but sensible, very limited use that you’re 100% on top of can be easy and effective causing zero problems.

A variation on the above is having a “world” or “level” scene which has variables/arrays/dicts containing the child objects within it. At least then you’re limiting scope to some extent.

As mentioned above, signals are a great option but you don’t want to be sending one every frame.

My personal preferred approach is to pass the object via the game event that made it necessary. So if you’re using a raycast / collision / mouse click / etc to decide what the target is then pick up the target object when this happens. Godot generally just hands you an object reference in the event.

So, there are many ways to do it, you just need to find a way that doesn’t end in spaghetti code and dependencies; the rule of thumb is that every scene should run individually without errors.