[Godot] onreadyキーワードはどういった場面で使うか?

Godot公式サイトへのボタン
完全無料の高機能ゲームエンジン「Godot」の解説を書いています。
公式サイトはこちら公式ドキュメント(Godot 4)公式ドキュメント(Godot 3)当サイトのGodot記事一覧はこちら
この記事はGodot 3.0の時代に書かれたものです。Godot 4.0では「onready」はアノテーション扱いとされ「@onready」と書き方が変わります。使い方は同じです。4.0では下記コードをそのまま使うとエラーとなりますのでご注意ください。

 

今日はGodotの「onready」キーワードについて調べます。

クラスの変数定義を見ると、

var a = 10
onready 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を付ける必要はありません。

 

コメント