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 節點的引用。

../../_images/nodes_and_scene_instances_player_scene_example.webp

有下列事項需注意:

var sprite2d
var camera2d

func _ready():
    sprite2d = get_node("Sprite2D")
    camera2d = get_node("Camera2D")

請注意,你是通過名稱來獲取節點的,和型別無關。上面的“Sprite”和“Camera2D”都是這些節點在場景中的名字。

../../_images/nodes_and_scene_instances_sprite_node.webp

如果你在“場景”面板中將 Sprite 節點重命名為“Skin”,那就必須在腳本裡把獲得節點的那一行敘述寫成 get_node("Skin")

../../_images/nodes_and_scene_instances_sprite_node_renamed.webp

Node paths

獲取節點的引用時,並不僅限於直接子節點。get_node() 函式支援使用路徑,有點類似檔瀏覽器裡的路徑。可以用斜杠分隔節點。

在下面這個實例場景中,腳本是附加在 UserInterface 節點上的。

../../_images/nodes_and_scene_instances_ui_scene_example.webp

有下列事項需注意:

var animation_player

func _ready():
    animation_player = get_node("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.

要刪除節點、將其從內容中釋放,你可以呼叫其 queue_free() 方法。這樣該節點的刪除工作就會被新增到佇列中,在目前影格完成處理後就會執行。刪除時,引擎會把該節點從場景中刪除,然後釋放物件記憶體中的物件。

sprite2d.queue_free()

在呼叫 sprite.queue_free() 之前,遠端場景樹是類似這樣的。

../../_images/nodes_and_scene_instances_remote_tree_with_sprite.webp

在引擎釋放節點後,遠端場景樹就不會再現實這個精靈了。

../../_images/nodes_and_scene_instances_remote_tree_no_sprite.webp

你也可以呼叫 free() 來立即刪除該節點。呼叫時需要小心,因為所有對它的引用都會立即變成 null。除非你知道自己在幹什麼,否則我們建議使用 queue_free()

釋放節點時也會釋放它的所有子項。多虧如此,只需刪除最頂端的父節點,就可以刪除整個場景樹分支了。

實體化場景

場景就是範本,你可以用來來建立任意數量的複製品。這樣的操作叫作產生實體(instancing),在程式碼中進行產生實體總共分兩步:

  1. 在程式碼中載入資源

  2. 要取得場景的實體,則必須使用 PackedScene.instance() 方法。

var scene = load("res://my_scene.tscn")

預載入場景可以提升使用者體驗,因為載入操作發生在編譯器讀取腳本時,而非運作時。這個功能是 GDScript 獨有的。

var scene = preload("res://my_scene.tscn")

scene (場景) 還不是節點,目前還打包在一個叫做 PackedScene (打包場景) 的特殊資源內。要真正建立節點,必須呼叫 PackedScene.instance() 函式。這個函式會回傳一個可以被新增到有效場景內的節點樹:

var instance = scene.instantiate()
add_child(instance)

拆成「載入 - 實體化」兩個步驟的優點是,載入過打包場景後就可以維持已載入的狀態,隨時拿來使用。這樣一來我們就可以根據需要建立任意數量的實體。特別適用於需要在有效場景內快速實體化多個敵人、子彈或是其他實體的情況。