.new() not assigning @onready variables

Godot Version

4.5 Stable

Question

I’m having issues with instantiating nodes through .new(). For whatever reason, it seems to leave the @onready variables null, even though I am assigning them. Does .new() not work with @onready variables that are assigned child nodes?

The variables in question:

@onready var personal_bubble: Area2D = $PersonalBubble
@onready var collision_detect: RayCast2D = $CollisionDetect
@onready var sprite: Sprite2D = $Sprite2D
@onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var animation_tree: AnimationTree = $AnimationTree
@onready var name_tag: Label = $NameTag

My _ready func which, as you can see, depends on one of the @onready variables:

func _ready() -> void:
	personal_bubble.mouse_entered.connect(func():
		sprite.material.set("shader_parameter/color", highlight_color)
		name_tag.label_settings.font_color = highlight_color
		)
	personal_bubble.mouse_exited.connect(func(): fade_highlight = true)
	
	set_up()

The way I’m understanding the documentation is that @onready vars are assigned prior to the _ready() function, so presumably this shouldn’t be happening? Which is why I’m wondering if this is an issue with assigning nodes specifically, though I’m not sure how I’m meant to get around that.

.new() only creates an instance of the specified node. Since you’re referencing child nodes, it looks like you probably wanted to instantiate a scene instead?

2 Likes

Also note that @onready and _ready is called the first time a Node enters the tree, not when it’s instantiated

1 Like

As a side note, strictly speaking, there’s no such thing as “onready variable”. @onready annotation relates only to the initial value assignment to the variable, which is delayed until just before _ready() is called. It’s exactly the same as writing that initial assignment at the start of _ready() function.

2 Likes

Ahh okay, I didn’t recognize that there was a difference. I assumed instantiating the root node of a scene would instantiate the scene. This is what I’d want to do instead, I presume?

Yes, exactly. (pre)load the scene, then instantiate it.

2 Likes

Great, thanks for the help and advice from everyone!