节点与场景实例
本指南将介绍如何获取节点、创建节点、将节点添加为子项、使用代码实例化场景。
获取节点
你可以通过调用 Node.get_node() 方法来获取节点的引用。子节点必须在场景树中才能成功。在父节点的 _ready()
函数中获取就可以保证这一点。
例如,如果有这样的场景树,并且你希望获得对 Sprite2D 和 Camera2D 节点的引用,以便在脚本中访问它们。
那么,你可以使用如下代码。
GDScriptC#
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 节点,你可以使用如下代码。
GDScriptC#
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()
将其添加为脚本所在节点的子项。
GDScriptC#
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()
方法。这样该节点的删除任务就会被添加到队列中,在当前帧完成处理后就会执行。删除时,引擎会把该节点从场景中删除,然后释放对象内存中的对象。
GDScriptC#
sprite2d.queue_free()
_sprite2D.QueueFree();
Before calling sprite2d.queue_free()
, the remote scene tree looks like this.
在引擎释放节点后,远程场景树就不会再现实这个精灵了。
你也可以调用 free()
来立即删除该节点。调用时需要小心,因为所有对它的引用都会立即变成 null
。除非你知道自己在干什么,否则我们建议使用 queue_free()
。
释放节点时也会释放它的所有子项。多亏如此,只需删除最顶端的父节点,就可以删除整个场景树分支了。
实例化场景
场景就是模板,你可以用来来创建任意数量的复制品。这样的操作叫作实例化(instancing),在代码中进行实例化总共分两步:
从本地硬盘加载场景。
创建加载到的 PackedScene 资源的实例。
GDScriptC#
var scene = load("res://my_scene.tscn")
var scene = GD.Load<PackedScene>("res://MyScene.tscn");
预加载场景可以提升用户体验,因为加载操作发生在编译器读取脚本时,而非运行时。这个特性是 GDScript 独有的。
GDScript
var scene = preload("res://my_scene.tscn")
此时的 scene
是个打包场景资源,而不是节点。要创建实际的节点,你需要调用 PackedScene.instantiate()。它会返回一棵节点树,你可以将其添加为当前节点的子节点。
GDScriptC#
var instance = scene.instantiate()
add_child(instance)
var instance = scene.Instantiate();
AddChild(instance);
此两步过程的优点在于,打包的场景可以保持加载状态并可以随时使用。例如,你就可以快速地对许多敌人或子弹进行实例化。
© 版权所有 2014-present Juan Linietsky, Ariel Manzur and the Godot community (CC BY 3.0). Revision b1c660f7
.
Built with Sphinx using a theme provided by Read the Docs.