ノードとシーンインスタンス
このガイドでは、ノードの取得、ノードの作成、それらを子として追加し、コードからシーンをインスタンス化する方法について説明します。
参考
Check the インスタンスの作成 tutorial to learn about Godot's approach to scene instancing.
ノードの取得
ノードへの参照を取得するには Node.get_node() メソッドを呼び出します。これが機能するには、子ノードがシーンツリーに存在する必要があります。親ノードの _ready() 関数でそれを取得することで、それが保証されます。
たとえばこのようなシーンツリーがあり、Sprite2DノードとCamera2Dノードへの参照を取得してスクリプト内でアクセスしたいとします。
これを行うには、次のコードを書きます。
var sprite2d
var camera2d
func _ready():
sprite2d = get_node("Sprite2D")
camera2d = get_node("Camera2D")
private Sprite2D _sprite2D;
private Camera2D _camera2D;
public override void _Ready()
{
base._Ready();
_sprite2D = GetNode<Sprite2D>("Sprite2D");
_camera2D = GetNode<Camera2D>("Camera2D");
}
ノードは型ではなく名前を使用して取得することに注意してください。上の"Sprite2D"と"Camera2D"はシーン内のノードの名前です。
シーンドックでSprite2Dノードの名前をSkinに変更した場合は、スクリプト内でノードを取得する行を get_node("Skin") に変更する必要があります。
ノードパス
ノードへの参照を取得する場合、直接の子を取得することに限定されません。 get_node() 関数はパスをサポートしており、ファイルブラウザを操作する場合と似ています。ノードを区切るにはスラッシュを追加します。
次のシーン例を考えてみましょう。UserInterfacノードにスクリプトがアタッチされています。
AnimationPlayerノードを取得するには、次のコードを使用します。
var animation_player
func _ready():
animation_player = get_node("ShieldBar/AnimationPlayer")
private AnimationPlayer _animationPlayer;
public override void _Ready()
{
base._Ready();
_animationPlayer = GetNode<AnimationPlayer>("ShieldBar/AnimationPlayer");
}
注釈
ファイル パスと同様に ".." を使用して親ノードを取得できますが、なるべくカプセル化を壊さないようにするためにこれを避けたほうがいいです。パスをスラッシュで開始して絶対パスにすることもできます。その場合、最上位のノードはアプリケーションの事前定義されたルートビューポートである "/root" になります。
シンタックスシュガー
2つの短縮表現を使用して、GDScriptのコードを短縮できます。まずメンバー変数の前に @onready アノテーションを置くと、 _ready() コールバックの直前に初期化されます。
@onready var sprite2d = get_node("Sprite2D")
get_node() には、ドル記号"$"という短い表記法もあります。これを取得するノードの名前またはパスの前に置きます。
@onready var sprite2d = $Sprite2D
@onready var animation_player = $ShieldBar/AnimationPlayer
ノード作成
コードからノードを作成するには、他のクラスベースのデータ型と同様に、new()メソッドを呼び出します。
スクリプトから新しく作成したノードの参照を変数にセットし、add_child() を呼び出すと自分のノードの子として追加できます。
var sprite2d
func _ready():
var sprite2d = Sprite2D.new() # Create a new Sprite2D.
add_child(sprite2d) # Add it as a child of this node.
private Sprite2D _sprite2D;
public override void _Ready()
{
base._Ready();
_sprite2D = new Sprite2D(); // Create a new Sprite2D.
AddChild(_sprite2D); // Add it as a child of this node.
}
ノードを削除してメモリから解放するには、ノードの queue_free() メソッドを呼び出します。これを行うとノードの処理が完了した後、ノードが削除キューに入れられます。削除キューに入れられたノードは現在のフレームの最後に実際に削除されます。その時点でエンジンはシーンからノードを削除し、メモリ内のオブジェクトを解放します。
sprite2d.queue_free()
_sprite2D.QueueFree();
sprite2d.queue_free() を呼び出す前のリモートシーンツリーは次のようになります。
エンジンがノードを解放すると、リモートシーンツリーにはスプライトが表示されなくなります。
あるいは free() を呼び出してノードを即座に破棄することもできます。この参照は即座に null になるため、扱いに注意する必要があります。これが何をしているのかわからない場合は queue_free() を使用することをお勧めします。
ノードを解放すると、そのノードのすべての子も解放されます。このおかげでシーンツリーのブランチ全体を削除するには、最上位の親ノードを解放するだけで済みます。
シーンのインスタンス化
シーンは必要なだけ複製を作成できるいわゆるテンプレートです。この操作はインスタンス化と呼ばれ、コードからの実行は次の2つの順序で行われます。
ローカルドライブからシーンをロードします。
ロードされた PackedScene リソースのインスタンスを作成します。
var scene = load("res://my_scene.tscn")
var scene = GD.Load<PackedScene>("res://MyScene.tscn");
シーンをプリロードすると、ロード操作は実行時ではなくコンパイラがスクリプトを読み取るときに実行されるため、ユーザー エクスペリエンスが向上します。この機能は GDScript でのみ使用できます。
var scene = preload("res://my_scene.tscn")
その時点で scene はまだノードではなく、パックされたシーンのリソースです。実際のノードを作成するには、 PackedScene.instantiate() 関数を呼び出す必要があります。これにより現在のノードの子として使用できるノードのツリーが返されます。
var instance = scene.instantiate()
add_child(instance)
var instance = scene.Instantiate();
AddChild(instance);
この2段階のプロセスの利点は、パックされたシーンをロードしたままにして、その場で新しいインスタンスを作成できることです。たとえば複数の敵や弾丸を素早くインスタンス化します。