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...
節點與場景實體
本指南將說明如何獲取節點、建立節點、將節點新增為子節點,以及如何用程式碼實體化場景。
也參考
請參閱 編輯實體 教學,進一步瞭解 Godot 處理場景實體化的方法。
取得節點
你可以透過呼叫 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() 方法支援路徑,有點像是在檔案總管中操作,使用斜線分隔各節點。
以下列範例場景為例,腳本掛載在 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() 之前,遠端場景樹看起來如下。
當引擎釋放該節點後,遠端場景樹就不會再顯示這個精靈了。
你也可以呼叫 free() 立即銷毀節點,但需謹慎使用,因為所有對該節點的參考會立即變成 null。除非你確定這樣做沒問題,否則建議用 queue_free()。
釋放節點時也會同時釋放其所有子節點。因此,若要刪除場景樹的整個分支,只需釋放最上層的父節點即可。
場景實體化
場景是可以重複產生多份副本的範本。這個動作稱為「實體化」,在程式碼中實體化場景需分兩個步驟:
從本地磁碟載入場景。
將載入的 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);
這種兩步驟的方式好處是可以維持場景資源已載入的狀態,隨時快速產生新實體。例如可用於即時生成多個敵人或子彈。