_ready() Not Calling When Adding New Button to Tree

Godot Version

v4.2.2.stable.official [15073afe3]

Question

Hello friends! I’ve come across an issue when trying to make contextual buttons appear systemically through code. I instantiate them first, set their text and variables unique to them (namely, the scripts they contain), then add them into the scene using add_child(button). Normally, this is where I’d expect the _ready() line to run, and all the code in the button to start working. However, although the buttons do show up onscreen and visually react to being pressed, none of their code runs at all. Why is that? Here is the code where I create the buttons if you’re interested:

func createOptions(options: Array):
optionList = Node2D.new()
add_child(optionList)
var i = 0

for opt in options:
	var button = butt.instantiate()
	button.text = opt.get("text", "")

	#optional
	button.goto = opt.get("goto", null)
	button.script = opt.get("script", null)
	#button.scripInputs = opt.get("inputs", [])

	# Add to scene
	
	optionList.add_child(button)

	# Positioning logic
	button.position = Vector2(
		storyText.position.x,
		storyText.position.y + storyText.size.y - buttonHeightCount
	)
	buttonHeightCount += button.size.y
	i += 1
buttonHeightCount = 0

Any help or insights would be appreciated, and if you have questions I would love to share more!

Can you post the button code?

1 Like

Ok, here’s the button code. I tried changing it a bunch and it didn’t seem to have any affect on whether or not the code actually ran, so I suspected that it wasn’t the issue. The setup for this scene is just a button object with a custom theme and this script attached:

extends Button
signal continueStory
signal addHP
signal battleStart
signal bossBattleStart
signal optionClicked
var goto
var scrip = “continueStory”
var scripInputs = [null]

func _ready():
pressed.connect(_on_pressed)

func _process(delta):
pass

func _on_pressed():
Signalbus.emit_signal(“optionClicked”, goto, scrip, scripInputs)

Put print statements in button’s functions to see if/when they get called.

Nothing prints because the code never gets called, but ideally it would get called when I add it as a child or when i click the buttons. Notably though, when debugging I noticed it runs the top lines of code (up until var scripInputs = [null]) when the button is first created. It just never runs any of the rest of the code.

Your code changes the script on the button here:

button.script = opt.get("script", null)

The script you posted is likely not attached to the button any more at the time you call add_child(), so its _ready() will not be executed.

1 Like

Ah, I see! I didn’t know that script was a recognized variable by godot! I realized I wrote “script” instead of “scrip” which is what I was using in the button code, and godot never gave me an error since “script” is a real variable. Thanks for pointing that out!