How to use @onready to get a Node in a @tools script

Godot Version

4.2.1

Question

I have the following code:

@tool
extends Panel

@onready var grid_container: GridContainer = $Grid/Container

func update_grid():
	grid_container.columns = columns_count

This doesn’t work because grid_container is always null because of the @onready annotation. But if I change it to this:

func update_grid():
	var grid_container = $Grid/Container
	grid_container.columns = columns_count

This works but it will require me to initialize every Node separately which is not that nice. What is the best way to handle this?

This is not a problem specific to your script. This is because @onready and _ready() happen before the children are ready themselves. An easy way to solve this is in _process().

var grid_container: GridContainer

func _process():
	if grid_container == null and ($Grid/Container).is_node_ready():
		grid_container = $Grid/Container
2 Likes

You can also try to await ready of your panel (and its children) in your update function:

func update_grid():
	if not is_node_ready():
		await ready

	grid_container.columns = columns_count
1 Like