Search code examples
godotgdscript

How can I move one Node3D to another Node3D's child in Godot 4.0? And how can I duplicate a random child of a Node3D


I am making some script for a game I'm making. The game's map is a randomly generated series of hallways, and there are different shaped hallways. For example, one hallway is straight, another turns, another turns and has a set of stairs that do down. If there is no way to do anything I mentioned above in the question, is there an alternative?

I haven't really tried anything yet for moving one node to another, because all the tutorials are outdated. For duplicating a random node, I tried something like this:

var parent_node = $Node3D
var random_index = randi() % parent_node.get_child_count()
var random_child = parent_node.get_child(random_index)
var duplicated_child = random_child.duplicate()

It gave me an error saying cannot call duplicate on a null instance.


Solution

  • I figured out your problem: You are trying to get the node: $Node3D and call .get_child_count() on it before the scene has finished loading. To fix this, add @onready at the beginning of each of the lines, or put the in the _ready() function. Doing this would make sure the code only runs when the scene is loaded and everything is ready. This is the final code I would suggest:

    @onready var parent_node = $Node3D
    
    func _ready():
        var random_index = randi() % parent_node.get_child_count()
        var random_child = parent_node.get_child(random_index)
        var duplicated_child = random_child.duplicate()
    

    You also said that you want to move the node to another parent node. I will assume you are trying to move the random node. So first lets add another variable for the new parent node:

    @onready var new_parent = $Node
    

    Replace $Node with the node you want to be the new parent.

    Next we want to add the child to the new parent in the _ready() function:

    new_parent.add_child(duplicated_child)
    

    You are now done unless you want to remove the node from the original parent, then you will add this after:

    parent_node.remove_child(duplicated_child)
    

    This is now the final Code:

    @onready var parent_node = $Node3D
    @onready var new_parent = $Node
    
    func _ready():
        var random_index = randi() % parent_node.get_child_count()
        var random_child = parent_node.get_child(random_index)
        var duplicated_child = random_child.duplicate()
        new_parent.add_child(duplicated_child)
        parent_node.remove_child(duplicated_child)