节点与场景实例
本指南将介绍如何获取节点、创建节点、将节点添加为子项、使用代码实例化场景。
获取节点
你可以通过调用 Node.get_node() 方法来获取节点的引用。子节点必须在场景树中才能成功。在父节点的 _ready()
函数中获取就可以保证这一点。
打个比方,如果你的场景树是这样的,并且你想要在脚本中获取 Sprite 和 Camera2D 节点的引用。
那么,你可以使用如下代码。
GDScriptC#
var sprite
var camera2d
func _ready():
sprite = get_node("Sprite")
camera2d = get_node("Camera2D")
private Sprite _sprite;
private Camera2D _camera2d;
public override void _Ready()
{
base._Ready();
_sprite = GetNode<Sprite>("Sprite");
_camera2d = GetNode<Camera2D>("Camera2D");
}
请注意,你是通过名称来获取节点的,和类型无关。上面的“Sprite”和“Camera2D”都是这些节点在场景中的名字。
如果你在“场景”面板中将 Sprite 节点重命名为“Skin”,那就必须在脚本里把获得节点的那一行语句写成 get_node("Skin")
。
节点路径
获取节点的引用时,并不仅限于直接子节点。get_node()
函数支持使用路径,有点类似文件浏览器里的路径。可以用斜杠分隔节点。
在下面这个实例场景中,脚本是附加在 UserInterface 节点上的。
要获取 Tween 节点,你可以使用如下代码。
GDScriptC#
var tween
func _ready():
tween = get_node("ShieldBar/Tween")
private Tween _tween;
public override void _Ready()
{
base._Ready();
_tween = GetNode<Tween>("ShieldBar/Tween");
}
备注
和文件路径一样,你可以使用“..”来获取父节点。最佳实践是不要这么做,避免破坏封装。你还可以让路径以斜杠开头,这样的路径是绝对路径,最上层的节点就是“/root”,即程序的预定义根视口。
语法糖
GDScript 中有两个速写法可以用来缩短代码。首先是在成员变量之前写 onready
关键字,这样这个变量就会刚好在 _ready()
回调之前初始化。
onready var sprite = get_node("Sprite")
还有一个 get_node()
的速记法:美元符号“$”。可以把它放在想要获取的名称或者节点路径之前。
onready var sprite = $Sprite
onready var tween = $ShieldBar/Tween
创建节点
要通过代码创建节点,请像其他任何基于类的数据类型一样,调用其 new()
方法。
你可以将新创建的节点的引用保存在一个变量中,然后调用 add_child()
将其添加为脚本所在节点的子项。
GDScriptC#
var sprite
func _ready():
var sprite = Sprite.new() # Create a new Sprite.
add_child(sprite) # Add it as a child of this node.
private Sprite _sprite;
public override void _Ready()
{
base._Ready();
_sprite = new Sprite(); // Create a new Sprite.
AddChild(_sprite); // Add it as a child of this node.
}
要删除节点、将其从内容中释放,你可以调用其 queue_free()
方法。这样该节点的删除任务就会被添加到队列中,在当前帧完成处理后就会执行。删除时,引擎会把该节点从场景中删除,然后释放对象内存中的对象。
GDScriptC#
sprite.queue_free()
_sprite.QueueFree();
在调用 sprite.queue_free()
之前,远程场景树是类似这样的。
在引擎释放节点后,远程场景树就不会再现实这个精灵了。
你也可以调用 free()
来立即删除该节点。调用时需要小心,因为所有对它的引用都会立即变成 null
。除非你知道自己在干什么,否则我们建议使用 queue_free()
。
释放节点时也会释放它的所有子项。多亏如此,只需删除最顶端的父节点,就可以删除整个场景树分支了。
实例化场景
场景就是模板,你可以用来来创建任意数量的复制品。这样的操作叫作实例化(instancing),在代码中进行实例化总共分两步:
从硬盘加载场景。
创建加载到的 PackedScene 资源的实例。
GDScriptC#
var scene = load("res://MyScene.tscn")
var scene = GD.Load<PackedScene>("res://MyScene.tscn");
预加载场景可以提升用户体验,因为加载操作发生在编译器读取脚本时,而非运行时。这个特性是 GDScript 独有的。
GDScript
var scene = preload("res://MyScene.tscn")
此时的 scene
是个打包场景资源,不是节点。要创建实际的节点,你需要调用 PackedScene.instance()。它返回的是一棵节点树,可以添加为当前节点的子节点。
GDScriptC#
var instance = scene.instance()
add_child(instance)
var instance = scene.Instance();
AddChild(instance);
此两步过程的优点在于,打包的场景可以保持加载状态并可以随时使用。例如,你就可以快速地对许多敌人或子弹进行实例化。