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() 函数中获取就可以保证这一点。

例如,如果有这样的场景树,并且你希望获得对 Sprite2D 和 Camera2D 节点的引用,以便在脚本中访问它们。

../../_images/nodes_and_scene_instances_player_scene_example.webp

那么,你可以使用如下代码。

var sprite2d
var camera2d

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

请注意,你是通过名称来获取节点的,而不是节点的类型。上面的“Sprite2D”和“Camera2D”都是这些节点在场景中的名字。

../../_images/nodes_and_scene_instances_sprite_node.webp

如果你在“场景”面板中将“Sprite2D”节点重命名为“Skin”,那就必须在脚本里把获得节点的那一行语句写成 get_node("Skin")

../../_images/nodes_and_scene_instances_sprite_node_renamed.webp

节点路径

获取节点的引用时,并不仅限于直接子节点。get_node() 函数支持使用路径,有点类似文件浏览器里的路径。可以用斜杠分隔节点。

在下面这个实例场景中,脚本是附加在 UserInterface 节点上的。

../../_images/nodes_and_scene_instances_ui_scene_example.webp

要获取 AnimationPlayer 节点,你可以使用如下代码。

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()

Before calling sprite2d.queue_free(), the remote scene tree looks like this.

../../_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 资源的实例。

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

预加载场景可以提升用户体验,因为加载操作发生在编译器读取脚本时,而非运行时。这个特性是 GDScript 独有的。

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

此时的 scene 是个打包场景资源,而不是节点。要创建实际的节点,你需要调用 PackedScene.instantiate()。它会返回一棵节点树,你可以将其添加为当前节点的子节点。

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

此两步过程的优点在于,打包的场景可以保持加载状态并可以随时使用。例如,你就可以快速地对许多敌人或子弹进行实例化。