Why instantiate() scene get_parent() don't return the good parent

Hello, I tried to instantiate a projectile but I need the initial position of the parent. They are only 2 classes : Player and Projectile. The get_parent() function of Projectile that is instanciated by Player don’t return to Player but to the World Scene. The code seems to work only if if manually set the parent of the Projectile within the Player, otherwise it doesn’t return the good parent.


if Input.is_action_just_pressed("action"):
		var projectile = projectile_path.instantiate()
		#projectile.parent = self # parent = Player (correct behavior)
		projectile.throwing_angle = 10


@export var parent : Node2D = null

func _ready():
	if parent == null:
			parent = get_parent() # parent = World (wrong behavior)

Instead of accessing get_parent() in _ready(), you should rather access it when you receive the NOTIFICATION_ENTER_TREE.


You mean like this ?


func _enter_tree():
	parent = get_parent()

func _ready():
	position = parent.position

It does I think the same (as I can see) and parent = get_parent() still return World.

But parent = self seems to have a weird behavior : If you click multiple times on the action button, the first self return a Projectile and all the other times returns @CharacterBody2D@number in the print(parent.name).

In Player.gd, you are adding the projectile to the world (owner). If you want the Player to be the parent, change owner.add_child(projectile) to add_child(projectile). However, that will add behavior you may not want (the projectile will move when the player moves).

1 Like

That’s indeed the behavior I don’t want haha. I want to control everything from Projectile if that’s possible

hi @Idlemast !

I dealt with something similar in my game, so I actually just added it to the root, then set that bullets position to the position of the Gun which is a child of the Player. You could alternatively add it to another node, like “bullet spawn parent” or something.

This is in my Gun.gd class which is then a component on Player.gd

	bullet.transform.origin = global_position

The gun, where the bullet ends up visually spawning from, is the pink square there.

1 Like

I know this solution works but that’s what I already made with this line :


projectile.parent = self

Because the code that I made may or may not require a parent. If not assigned, I would like to assign the parent, that’s what I want to do precisely in the Projectile class.

And because I don’t understand why get_parent() doesn’t return the actual parent

I don’t believe this is a correct statement, any projectile you’re trying to spawn (any Node in Godot) will require being on the SceneTree childed to some node, which will require a parent. Using add_child will parent the child to whatever that function is called on, in your case owner, and this is happening in your gif!

In general, setting the parent that way (using node.parent = x does not work, there is no parent property like this on the Node class in Godot4 (are you by chance using Godot3?).

You can call get_parent() after calling add_child() and you should just get back owner object. But overall, the only way to set a parent is by using the add_child method, unless I am misunderstanding your ask. Are you just trying to shoot a projectile?

1 Like

There’s a reparent() function built in. Maybe use that. It should be visible in auto complete, and ctrl clicking on it will show you the arguments. I don’t remember the parameters as of right now.

1 Like

owner in my case is the main scene with the collision, the enemy, etc…
And parent is a property that I use to assign the starting position of the projectile, and maybe other things.
I know that we can’t assign a parent, but if I instantiate a Projectile using instantiate() and added that in the World with add_child() (to act like a projectile)…

I just remembered that Projectile are childs of World so that’s why I need to assign the starting position with Player, good lord have mercy.

So your proposition is correct

1 Like

OK great! And I see - also yes, I’m doing this in the same way above.

And great to hear that was the solution!!