Why do we use onready when creating the Scoreboard and NameField node references?

Just in case anyone had the same confusion as I did about onready...

It turns out I didn't understand Nathan's explanation of onready, as I was very confused when I saw his code using onready when creating the references to the Scoreboard and NameField nodes in ScoreForm.gd.

onready var scoreboard := $Scoreboard
onready var name_field := $HBoxContainer/NameField

Surely, I thought, that as this code existed in the ScoreForm node (the parent), and as the child nodes will first be instantiated and become ready before the ScoreForm node, then onready wouldn't be required and we could just make the assignments without using it. However, this isn’t the case, and the code won't work.

I did a little Googling to see if I could figure out why in a little more detail, and it appears there’s an important caveat for member variables (the variables created outside of the functions) which explains why onready is required.

It seems that assignments to member variables without onready will occur before any child nodes are ready. The fact that the assignment is done in the parent doesn't seem to matter, as it happens as soon as the node enters the scene tree (and as it's the parent, it'll enter before its children). If we don’t use onready, it means we’ll be attempting to assign references to the child nodes before they’re available.

Moral of the story? Read the lessons properly and trust Nathan and the team. :)

A more detailed explanation can be found here:


  • Xananax replied

    All root variables are set when the node is created.

    The onready annotation re-assigns a new value after the node is ready.

    The code:

    onready var x = $NodeX

    func _ready():
      var y = $NodeY

    is equivalent to:

    var x = null

    func _ready():
      var y = $NodeY
      x = $NodeX

    A node is "ready" when all its children are ready.

    2 loves
  • k
    karl.botragyi replied

    Xananax, that's the distinction I wasn't aware of (and led to my confusion as to why we needed onready if we were only setting up dependencies on the node's children). I hadn't appreciated that there was a difference between a node being created, and it becoming ready. I thought they were the equivalent.

    Thanks for helping me figure this out (and for finding a way to express what I took several paragraphs to say in a single sentence).

    2 loves