2min read
Game Dev
Godot Engine
December 16, 2018
While working on a card game with Godot (the code will soon be open sourced), I had to reparent a node from one parent to another. Here it is two simple ways to do it.
Essentially I wanted to move the Card
node from the PlayerCards
container
to the Field
container (a grid where the cards are played).
Let’s take an example for the sake of clarity: suppose that we want to move the card from PlayerCards/Container0
node to
Field/Container4
node.
The code that I came up at first was:
# Field.gd (script attached to Field node)
func add_card_at_position(card_container, field_container_index):
# get the Card node
var card = card_container.get_child(0)
# move the card into the Container4 (hyp: container_index = 4)
get_node("Container" + str(field_container_index)).add_child(card)
# free memory
card_container.queue_free()
In our exampe card_container
, the first parameter in the function, is a reference to the Container4
node.
So we get its child, that essentially is a Card
node and then try to reparent it to move it into the field.
But I had this error:
Can't add child 'Card' to 'Container4', already has a parent 'Container0'.
The problem is that I’m trying to move the Card
node that already has a parent.
In Godot one node can have only one parent at a time.
Since Godot doesn’t have a reparent()
method (as far as I am aware
at least, but I’m going to ask to the development team on Discord and update this post eventually),
we have to make this thing by ourselves.
Pretty simple, you need to remove the node from the parent before assign it to a new one:
func add_card_at_position(card_container, field_container_index):
# duplicate is needed to workaround the error
var card = card_container.get_child(0)
# remove card from its parent (ugh...) <----- solution
card_container.remove_child(card) # <----- solution
# free memory
card_container.queue_free()
# add child to the Container4 (hyp: container_index = 4)
get_node("Container" + str(field_container_index)).add_child(card)
duplicate()
Another workaround that can be useful in some cases is
to simply create a duplicate of the Card
node and then
move the cloned object to the Field
.
func add_card_at_position(card_container, field_container_index):
# duplicate is needed to workaround the error
var card = card_container.get_child(0).duplicate()
# free memory
card_container.queue_free()
# add child to the Container4 (hyp: container_index = 4)
get_node("Container" + str(field_container_index)).add_child(card)
If you need to duplicate hundreds of objects in a short time frame, then this may not be the best solution for you.