Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
節點與資源¶
本指南將介紹如何獲取節點、建立節點、將節點新增為子項、使用程式碼產生實體場景。
建立節點¶
你可以通過呼叫 Node.get_node() 方法來獲取節點的引用。子節點必須在場景樹中才能成功。在父節點的 _ready()
函式中獲取就可以保證這一點。
打個比方,如果你的場景樹是這樣的,並且你想要在腳本中獲取 Sprite 和 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");
}
請注意,你是通過名稱來獲取節點的,和型別無關。上面的“Sprite”和“Camera2D”都是這些節點在場景中的名字。
如果你在“場景”面板中將 Sprite 節點重命名為“Skin”,那就必須在腳本裡把獲得節點的那一行敘述寫成 get_node("Skin")
。
Node paths¶
獲取節點的引用時,並不僅限於直接子節點。get_node()
函式支援使用路徑,有點類似檔瀏覽器裡的路徑。可以用斜杠分隔節點。
在下面這個實例場景中,腳本是附加在 UserInterface 節點上的。
有下列事項需注意:
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():
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();
在呼叫 sprite.queue_free()
之前,遠端場景樹是類似這樣的。
在引擎釋放節點後,遠端場景樹就不會再現實這個精靈了。
你也可以呼叫 free()
來立即刪除該節點。呼叫時需要小心,因為所有對它的引用都會立即變成 null
。除非你知道自己在幹什麼,否則我們建議使用 queue_free()
。
釋放節點時也會釋放它的所有子項。多虧如此,只需刪除最頂端的父節點,就可以刪除整個場景樹分支了。
實體化場景¶
場景就是範本,你可以用來來建立任意數量的複製品。這樣的操作叫作產生實體(instancing),在程式碼中進行產生實體總共分兩步:
在程式碼中載入資源
要取得場景的實體,則必須使用 PackedScene.instance() 方法。
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 (打包場景) 的特殊資源內。要真正建立節點,必須呼叫 PackedScene.instance() 函式。這個函式會回傳一個可以被新增到有效場景內的節點樹:
var instance = scene.instantiate()
add_child(instance)
var instance = scene.Instantiate();
AddChild(instance);
拆成「載入 - 實體化」兩個步驟的優點是,載入過打包場景後就可以維持已載入的狀態,隨時拿來使用。這樣一來我們就可以根據需要建立任意數量的實體。特別適用於需要在有效場景內快速實體化多個敵人、子彈或是其他實體的情況。