Accessing a child node from an instanced scene.

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

Hello! It’s my first question here, glad to start my journey with you!

I just finished the Dodge the Creeps tutorial, and while i mostly understood, there is this part of the code that bugs me:

func _on_MobTimer_timeout():
# Choose a random location on Path2D.
$MobPath/MobSpawnLocation.set_offset(randi())
# Create a Mob instance and add it to the scene.
var mob = Mob.instance()
add_child(mob)
# Set the mob's direction perpendicular to the path direction.
var direction = $MobPath/MobSpawnLocation.rotation + PI / 2
# Set the mob's position to a random location.
mob.position = $MobPath/MobSpawnLocation.position
# Add some randomness to the direction.
direction += rand_range(-PI / 4, PI / 4)
mob.rotation = direction
# Set the velocity (speed & direction).
mob.linear_velocity = Vector2(rand_range(mob.min_speed, mob.max_speed), 0)
mob.linear_velocity = mob.linear_velocity.rotated(direction)

The part is mob.linear_velocity.

In the tutorial, they make itso the root node from the Mob Scene is the RigidBody, which contains a linear velocity variable.
In my version, the RigidBody is the child of a Node2D node, which does not contain a linear velocity variable.

The hierarchy looks like that:

MobNode
    RigidBody

I want to edit a var in the RigidBody, without a direct access to it.
I tried something like replacing

mob.linear_velocity = mob.linear_velocity.rotated(direction)

with

$RigidBody.linear_velocity = mob.linear_velocity.rotated(direction)
                                      or
get_node("/root/mob/rigidbody").linear...

What would the syntax be?

The Mob scene is not directly instanced in the main scene. If i understand it correctly, it’s the script that creates an instance by referencing another scene.

If someone could clarify this to me, and explain me the way of the get_nodes, I’d be so glad. Thanks!

:bust_in_silhouette: Reply From: kidscancode

Why did you make your rigid body the child of a Node2D? What is the Node2D going to do? The rigid body is what moves, so what purpose does an extra parent node serve? There’s a reason that it’s done that way in the tutorial. Extra parent nodes for no reason just increase complexity (and potentially break things).

That said, you can get any node with get_node(). If you have a reference to your mob scene (the Node2D), then you call get_node() to get its child.

mobnode.get_node("RigidBody").linear_velocity

True that i could make the RigidBody the base Node. Just thought that it was good practice to have a basic node as root? I made my life difficult for nothing :slight_smile:

I tried this, but don’t understand what is generated when this runs:

var mob = Mob.instance()
	add_child(mob)

I found a workaround by compartimenting better: i define the velocity inside the mob script.

But yeah, my problems stem from a bad choice of root.

Thanks!

Solfatare | 2020-02-17 11:07

I tried this, but don’t understand what is generated when this runs:

var mob = Mob.instance()
add_child(mob)

Mob is a scene. Any scene you want it to be, as defined earlier on in the tutorial:

export (PackedScene) var Mob

Think of that scene as a very detailed description of something. However, it still isn’t that something, it’s just it’s description. But given you have that description, you can use it for modeling that exact something by precisely following the description. This is what the call to instance does. Now you have something, but it’s still lingering in the void. So lastly we have to integrate it into the real world. That’s what add_child is for. The script you’re running is attached to a node. A node that already is a part of the real world, sitting satisfied in a scene tree. So we order that node to take our newly created something by the hand, cautiously introducing it to the real world. :wink:

As long as you keep the mob-variable around you can access the instance by it, e.g.:

mob.get_node("RigidBody").linear_velocity

That’s assuming your Mob-scene has a child that is named (!) “RigidBody” (i.e. it’s not the type that’s relevant here, but the name). Furthermore it’s assuming that this child has a property linear_velocity that you can access.

However, if you loose access to the mob-variable that isn’t a drama either! As you have added your Mob-scene to the tree, you can now access it the same way like any other node in the tree, e.g. assuming your Mob-scene is named “Mob”:

get_node("Mob/RigidBody").linear_velocity

Hope this helps. I would recommend you read this as well!

njamster | 2020-02-17 12:32

Very,very helpful. Thanks!

Solfatare | 2020-02-17 17:18

:bust_in_silhouette: Reply From: Wodsobe Dobe

You could right-click and click the “editable children” button, or click make local. That’s how I do it.