完全無料の高機能ゲームエンジン「Godot」の解説を書いています。
公式サイトはこちら / 公式ドキュメント(Godot 4) / 公式ドキュメント(Godot 3) / 当サイトのGodot記事一覧はこちら
この記事はGodot 3.0の時代に書かれたものです。Godot 4.0では「onready」はアノテーション扱いとされ「@onready」と書き方が変わります。使い方は同じです。4.0では下記コードをそのまま使うとエラーとなりますのでご注意ください。
今日はGodotの「onready 」キーワードについて調べます。
クラスの変数定義を見ると、
var a = 10onready var a = 10と、onreadyキーワードを付けているもの、付けていないものがあります。これは何を意味しているのでしょうか?
ちなみに2番目の onready var a = 10 は、実はonreadyを付ける意味はありません。以下の記事に使い方と理由を書きました。(おまじないのように全てにonreadyを付けている人がいましたので、解説します)
onreadyはシーンの _ready を再現するもの
Godotの特長として、ツリーオブジェクトは上から下へアクティブ化されます 。これをまず押さえてください。
たとえばノードが以下の構成になっていたとします。

トップのNode2Dにスクリプトをアタッチし、コードを以下のように書いたとします。
var n = $Labelすると、実行時にエラーになります。(書いた時点ですでに警告が出ますが)
なぜかというと、Node2Dのクラス変数が初期化される時点では、まだLabelノードが実体化していないため、その存在を n に代入することができないのです。
冒頭に書いたとおり、ツリーオブジェクトは上から下へアクティブ化され、加えてスクリプトのクラス変数は、アクティブ化と同時に実行されます。Labelの実体化はこのあとになります。
Node2Dのスクリプトが実行される時点では、Labelはまだ単なる定義にすぎないのです。
実体がないオブジェクトを代入しようとすると、Godotでは暗黙的にNULLになるのではなく、実行時エラーとなります。この仕様のおかげで、変数には確実に存在するオブジェクトのみが格納され、NULLを参照しようとしてエラー停止することがありません。安心して変数にアクセスできるのです。
そうなると、n に代入できるのはシーン全体が実体化(インスタンス化)したあと。つまり func _ready() が動くときになります。
正しく書くと以下のようになります。
var n
func _ready():
n = $Labelこれは正しく動き、nにはLabelの実体が代入されます。
さて、今回は n がたった1つなのでいいのですが、このような処理をしたい変数が5個、10個とたくさんあったらどうでしょうか?
全部を var 定義し、その代入を _ready() に書くとなるとコード量がかなり増えますし、変数を加えたり削除したりするたびに _ready() 内も編集しなければなりません。
ここでようやっと onready キーワード になります。
onready を付けた変数は、上記の _ready() と同じ動きを再現してくれるのです。
つまり
onready var n = $Labelと書くことができます。これは正しく動きます。
このコードが実行されるときにはまだ Label は実体化していませんが、Godotが暗黙的に実行を遅らせてくれ、ツリーが生成し終わったときに改めて代入してくれるのです!
たくさんの代入定義があっても、定義のみを書き換えれば済みます。定義は1行に収まるので、コードも見やすく、編集しやすくなるのです。
シーンオブジェクトをクラス変数に代入するときに、onreadyが必要
意味のない onready
onready var a = 10改めて冒頭のコードです。
onreadyの意味が分かれば、これが無意味なコードだということもわかりますね。
a には整数10を代入しているだけで、10はツリーオブジェクトではありません。つまりいつ呼び出してもまったくかまわないのです。試しにonreadyを削除しても、問題なく実行できます。
全てのクラス変数にonreadyを付ける必要はありません。

