Node.add_child overriding the child's variable value

Godot Version

v4.5.1

Question

I am trying to generate a collection of cards for a simple memory-match making game. I created a “Card” scene that is a StaticBody3D at it’s root and added a var pairId to its attached script. In the game I preload the Card scene:

var cardScene = preload(“res://card.tscn”)

Then when I am setting up the cards I call:

func createCard(pairId : int) → StaticBody3D:
var card = cardScene.instantiate()
card.pairId = pairId
return card

Then I add the created cards to an existing “Cards” node in the game scene like this:

card.name = “Card” + str(row) + str(col)
print(card.name + " " + str(card.pairId))
$Cards.add_child(card)
print($Cards.get_child(cardIndex).name + " " + str($Cards.get_child(cardIndex).pairId))

But add_child is resetting the pairId to 0. So the printing logs look like this:

Card00 1
Card00 0
Card01 0
Card01 0
Card10 0
Card10 0
Card11 1
Card11 0

How is pairId getting set to 0 here?
Thanks.

Who calls createCard()?

It’s called earlier in my setup() method in the game scene. It’s the same method that then adds the card to $Cards

Let’s see that code.

func setup() -> void:
	#setup variables
	mapSize = level * 2
	numberOfPairs = (mapSize * mapSize) / 2 
	movesLeft = (numberOfPairs * 1.5) as int
	foundPairs = 0
	
	#setup hud
	$HUD/Level.text = str(level)
	$HUD/MovesLeft.text = str(movesLeft)
	
	#setup cards
	var cards = []
	for i in range(numberOfPairs):
		cards.append(createCard(i))
		cards.append(createCard(i))
	cards.shuffle()
	var cardIndex = 0
	var startPosZ = -1 * (cardOffset_z * (mapSize - 1))
	var startPosX = -1 * (cardOffset_x * (mapSize - 1))
	
	for row in range(mapSize):
		for col in range(mapSize):
			var cardPosX = startPosX + (col)
			var cardPosZ = startPosZ + (row)
			var card = cards[cardIndex]
			card.position.x = cardPosX
			card.position.z = cardPosZ
			card.name = "Card" + str(row) + str(col)
			print(card.name + " " + str(card.pairId))
			$Cards.add_child(card)
			print($Cards.get_child(cardIndex).name + " " + str($Cards.get_child(cardIndex).pairId))
			cardIndex += 1

What gets printed if you call $Cards.print_tree_pretty() at the end of setup()

Card00 1
Card00 0
Card01 1
Card01 0
Card10 0
Card10 0
Card11 0
Card11 0
 ┖╴Cards
    ┠╴Card00
    ┃  ┠╴Border
    ┃  ┠╴MeshInstance3D
    ┃  ┃  ┖╴Face
    ┃  ┖╴CollisionShape3D
    ┠╴Card01
    ┃  ┠╴Border
    ┃  ┠╴MeshInstance3D
    ┃  ┃  ┖╴Face
    ┃  ┖╴CollisionShape3D
    ┠╴Card10
    ┃  ┠╴Border
    ┃  ┠╴MeshInstance3D
    ┃  ┃  ┖╴Face
    ┃  ┖╴CollisionShape3D
    ┖╴Card11
       ┠╴Border
       ┠╴MeshInstance3D
       ┃  ┖╴Face
       ┖╴CollisionShape3D

Is there a script attached to card? If yes, let’s see it. Something in its _ready() likely sets the id to 0. Or you have an assignment in @onready declaration.

Interesting. I didn’t realize the _ready() was called during the add child method. That would definitely do it. And now I’ve learned something new!

Thanks for all the help. :grinning_face_with_smiling_eyes:

1 Like

Look at _ready() description in Node class reference:

1 Like