setting independent movement for a child node

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

After a node has been instanced as a child of another, is there a way to set it to that it disregards its parent’s coordinates?

I’m creating a projectile shooter whose projectiles move with my character. It is quite weird.

:bust_in_silhouette: Reply From: kidscancode

The correct solution is don’t make the projectile a child of the character. Add it to the scene node or a container. The simplest way to do this is to use get_parent().add_child(projectile), although that comes with some drawbacks, as you have to make sure your character has a parent node.

Alternatively, you can add a Node to your character and add the projectiles to that. Node doesn’t have position information, and so it won’t pass any position to its children.

When I try tried this, the projectiles seem to spawn off screen (despite the fact I set their position beforehand)

Do I need to set their positions some other way?

mimboy | 2018-11-24 18:48

:bust_in_silhouette: Reply From: Xrayez

Add projectile nodes to the parent node that doesn’t move, not character.

You can also set projectile nodes as top level, this will disregard parent’s transform:

func _ready():
    set_as_toplevel(true)

Also, you can add a dummy Node to your character and spawn your projectiles there:

var dummy = Node.new()
character.add_child(dummy) # can be setup via scene ofcourse

dummy.add_child(projectile)

The dummy node doesn’t inherit from Node2D so it will not pass down parent’s transform to its children!

When I tried this, the projectiles seem to spawn off screen (despite the fact I set their position beforehand)

extends Area2D

var cooldownReady = true
var alternatingFire = 'left'
onready var projectile = preload("res://scenes/Player/Fire/allyProjectile.tscn")

func _ready():	
	pass
func _process(delta):
	if Input.is_action_pressed("ui_select") and cooldownReady == true:
		fireGun(alternatingFire)
	elif Input.is_action_pressed("ui_select"):
		# oncooldown
		pass


    func fireGun(direction):
    	cooldownReady = false
    	$CooldownTimer.start()
    	var firedProjectile = projectile.instance()
    	if direction == 'left':
    		firedProjectile.position = $LeftGun.position
    		alternatingFire = 'right'`enter code here`
    	elif direction == 'right':
    		firedProjectile.position = $RightGun.position
    		alternatingFire = 'left'
    	$projectileRef.add_child(firedProjectile)
    	
    func _on_CooldownTimer_timeout():
    	cooldownReady = true

Do I need to set their positions some other way?

(The alternating fire is for the character’s 2 pistols, every odd function call fires first pistol and the other’s fire second. projectileRef is the node I added to the player)

mimboy | 2018-11-24 18:47

Try firedProjectile.global_position = $LeftGun.global_position

position works locally relative to a node, so when you’re trying to set projectile’s position relatively to character’s one, it will spawn projectile at Vector2(0,0), which in global coordinates means “off the screen”.

Xrayez | 2018-11-25 08:11

This works perfectly. Thank you!

mimboy | 2018-11-25 08:32