Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
節點與場景實體
本指南將說明如何獲取節點、建立節點、將節點新增為子節點,以及如何用程式碼實體化場景。
也參考
Check the 編輯實體 tutorial to learn about Godot's approach to scene instantiation.
取得節點
你可以透過呼叫 Node.get_node() 方法來取得節點的參考。要讓這個方法正常運作,該子節點必須已經存在於場景樹中。在父節點的 _ready() 函式中取得節點可以保證這一點。
If, for example, you have a scene tree like this, and you want to get a reference to the Sprite2D and Camera2D nodes to access them in your script.
你可以使用以下程式碼來達成。
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() 方法支援路徑,有點像是在檔案總管中操作,使用斜線分隔各節點。
以下列範例場景為例,腳本掛載在 UserInterface 節點上。
要取得 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」,也就是應用程式預設的根視窗。
語法糖
在 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():
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() 方法。這會將節點排入佇列,在本幀處理結束後刪除。屆時,Godot 會把該節點從場景移除並釋放記憶體資源。
sprite2d.queue_free()
_sprite2D.QueueFree();
在呼叫 sprite2d.queue_free() 之前,遠端場景樹看起來如下。
當引擎釋放該節點後,遠端場景樹就不會再顯示這個精靈了。
You can alternatively call free() to immediately destroy the node. You
should do this with care as any reference to it will instantly become invalid.
We recommend using queue_free() unless you know what you're doing.
釋放節點時也會同時釋放其所有子節點。因此,若要刪除場景樹的整個分支,只需釋放最上層的父節點即可。
Instantiating scenes
Scenes are templates from which you can create as many reproductions as you'd like. This operation is called instantiation, and doing it from code happens in two steps:
從本地磁碟載入場景。
將載入的 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);
The advantage of this two-step process is you can keep a packed scene loaded and create new instances on the fly. For example, to quickly instantiate several enemies or bullets.