Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
SceneTree
通过节点层次结构管理游戏循环。
描述
作为最重要的类之一,SceneTree 管理着场景中节点的层次结构以及场景本身。节点可以进行添加、获取、移除等操作。整个场景树都可以暂停(因此当前场景也可以暂停)。场景可以加载、切换、重新加载。
你还可以使用 SceneTree 将节点分组管理:你想要创建多少分组都可以,每个节点都可以添加到若干个组中,例如“敌人”组。然后你可以遍历这些分组,甚至可以对指定分组中的所有节点执行调用方法、设置属性等操作。
SceneTree 是引擎所使用的默认 MainLoop 实现,因此负责游戏循环。
教程
属性
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
方法
void |
call_group(group: StringName, method: StringName, ...) vararg |
void |
call_group_flags(flags: int, group: StringName, method: StringName, ...) vararg |
change_scene_to_file(path: String) |
|
change_scene_to_packed(packed_scene: PackedScene) |
|
create_timer(time_sec: float, process_always: bool = true, process_in_physics: bool = false, ignore_time_scale: bool = false) |
|
get_first_node_in_group(group: StringName) |
|
get_frame() const |
|
get_multiplayer(for_path: NodePath = NodePath("")) const |
|
get_node_count() const |
|
get_node_count_in_group(group: StringName) const |
|
get_nodes_in_group(group: StringName) |
|
has_group(name: StringName) const |
|
void |
notify_group(group: StringName, notification: int) |
void |
notify_group_flags(call_flags: int, group: StringName, notification: int) |
void |
queue_delete(obj: Object) |
void |
|
void |
set_group(group: StringName, property: String, value: Variant) |
void |
set_group_flags(call_flags: int, group: StringName, property: String, value: Variant) |
void |
set_multiplayer(multiplayer: MultiplayerAPI, root_path: NodePath = NodePath("")) |
void |
信号
当 node
进入该树时发出。
node_configuration_warning_changed(node: Node) 🔗
当 node
的 Node.update_configuration_warnings() 被调用时发出。仅在编辑器中发出。
当 node
退出该树时发出。
当 node
的 Node.name 被更改时发出。
physics_frame() 🔗
在该树中的每个节点上调用 Node._physics_process() 之前立即发出。
process_frame() 🔗
在该树中的每个节点上调用 Node._process() 之前立即发出。
tree_changed() 🔗
每当该树的层次结构发生变化(节点被移动、重命名等)时发出。
tree_process_mode_changed() 🔗
当树内任意节点的 Node.process_mode 更改时触发。仅在编辑器中触发,以更新禁用节点的可见性。
枚举
enum GroupCallFlags: 🔗
GroupCallFlags GROUP_CALL_DEFAULT = 0
没有特殊行为地调用组内的节点(默认)。
GroupCallFlags GROUP_CALL_REVERSE = 1
按相反的树层次结构顺序调用组内的节点(所有嵌套子节点都在其各自的父节点之前调用)。
GroupCallFlags GROUP_CALL_DEFERRED = 2
在当前帧(可以是处理帧或物理帧)末尾调用组内的节点,类似于 Object.call_deferred()。
GroupCallFlags GROUP_CALL_UNIQUE = 4
即使在同一帧中执行多次,也仅调用组内的节点一次。必须与 GROUP_CALL_DEFERRED 结合使用才能工作。
注意:不考虑不同的参数。因此,当使用不同的参数执行相同的调用时,只会执行第一个调用。
属性说明
bool auto_accept_quit = true
🔗
如果为 true
,则应用程序会自动接受退出请求。
移动平台见 quit_on_go_back。
当前加载的主场景的根节点,通常是 root 的直接子节点。另见 change_scene_to_file()、change_scene_to_packed()、reload_current_scene()。
警告:直接设置该属性可能无法正常工作,因为这样不会在场景树中添加删除节点。
bool debug_collisions_hint = false
🔗
如果为 true
,从编辑器中运行游戏时会显示碰撞形状,方便调试。
注意:这个属性不应在运行时更改。在运行项目时更改 debug_collisions_hint 的值不会有想要的效果。
如果为 true
,从编辑器中运行游戏时会显示导航多边形,方便调试。
注意:这个属性不应在运行时更改。在运行项目时更改 debug_navigation_hint 的值不会有想要的效果。
bool debug_paths_hint = false
🔗
如果为 true
,从编辑器中运行游戏时,来自 Path2D 和 Path3D 节点的曲线将可见以进行调试。
注意:该属性没有被设计为在运行时更改。在项目运行时更改 debug_paths_hint 的值不会产生预期的效果。
编辑器中当前正在编辑场景的根节点。通常是 root 的直接子节点。
注意:该属性在发布版本中不起任何作用。
bool multiplayer_poll = true
🔗
如果为 true
(默认值),则在 process_frame 期间为该 SceneTree 启用 MultiplayerAPI 的自动轮询。
如果为 false
,则需要手动调用 MultiplayerAPI.poll() 以处理网络数据包并下发 RPC。这允许在一个不同的循环(例如物理、线程、特定时间步长)中运行 RPC,并在从线程访问 MultiplayerAPI 时进行手动 Mutex 保护。
如果为 true
,则会将场景树视为已暂停,会导致下列行为:
停止 2D 和 3D 物理,包括碰撞检测和相关信号。
可能不再调用每个节点的 Node._process()、Node._physics_process()、Node._input() 等回调方法,具体由各节点的 Node.process_mode 决定。
bool physics_interpolation = false
🔗
如果为 true
,则渲染器将在最后两个变换之间插入物理对象的变换,这样即使物理刻度与渲染帧不一致,也能看到平滑的运动。
该属性的默认值由 ProjectSettings.physics/common/physics_interpolation 控制。
如果为 true
,则该应用程序会在导航返回时自动退出(例如在 Android 上使用系统“返回”键)。
禁用这个选项时,如果要处理“返回”按钮,请使用 DisplayServer.WINDOW_EVENT_GO_BACK_REQUEST。
Window get_root()
场景树的根 Window。这是场景树的最顶层 Node,始终存在。绝对 NodePath 始终从这个节点开始。加载的 current_scene 以及“项目设置”中配置的自动加载可能也是根节点的子节点。
警告:请勿删除该节点。删除会导致不稳定的行为并引起崩溃。
方法说明
void call_group(group: StringName, method: StringName, ...) vararg 🔗
在该树内添加到给定 group
的每个节点上调用 method
。你可以通过在该方法调用末尾指定参数来将参数传递给 method
。无法调用 method
的节点(因为该方法不存在或参数不匹配)将被忽略。另见 set_group() 和 notify_group()。
注意:该方法立即作用于所有选定的节点,这可能会在某些性能密集型情况下导致卡顿。
注意:在 C# 中,当引用内置的 Godot 方法时,method
必须使用 snake_case。最好使用 MethodName
类中公开的名称,以避免在每次调用时分配新的 StringName。
void call_group_flags(flags: int, group: StringName, method: StringName, ...) vararg 🔗
在树内添加到给定 group
的每个节点上调用给定的 method
。使用 flags
自定义该方法的行为(请参阅 GroupCallFlags)。method
的附加参数可以在该方法的末尾传递。无法调用 method
的节点(因为该方法不存在或参数不匹配)将被忽略。
# 在帧末尾以相反的树顺序,在 “enemies” 组的所有节点上调用 “hide”。
get_tree().call_group_flags(
SceneTree.GROUP_CALL_DEFERRED | SceneTree.GROUP_CALL_REVERSE,
"enemies", "hide")
注意:在 C# 中,当引用内置的 Godot 方法时,method
必须使用 snake_case。最好使用 MethodName
类中公开的名称,以避免在每次调用时分配新的 StringName。
Error change_scene_to_file(path: String) 🔗
将位于给定路径 path
的场景加载进一个 PackedScene 并新建其实例,然后将正在运行的场景修改为这个场景。
成功时返回 @GlobalScope.OK;如果 path
不能被加载到一个 PackedScene 中,则返回 @GlobalScope.ERR_CANT_OPEN;如果该场景无法被实例化,则返回 @GlobalScope.ERR_CANT_CREATE。
注意:有关操作顺序的详细信息,请参阅 change_scene_to_packed()。
Error change_scene_to_packed(packed_scene: PackedScene) 🔗
将正在运行的场景更改为给定 PackedScene 的新实例(新实例必须有效)。
成功时返回 @GlobalScope.OK,场景无法被实例化时返回 @GlobalScope.ERR_CANT_CREATE,场景无效时返回 @GlobalScope.ERR_INVALID_PARAMETER。
注意:当 change_scene_to_packed() 被调用时,操作按以下顺序发生:
当前场景节点被立即从树中移除。从那时起,在当前(传出)场景上调用的 Node.get_tree() 将返回
null
。current_scene 也将变为null
,因为新场景尚不可用。在帧末尾时,已从树中移除的、之前的当前场景将被删除(从内存中释放),然后新场景将被实例化并添加到树中。Node.get_tree() 和 current_scene 将恢复正常工作。
这确保了两个场景不会同时运行,并且仍然会以类似于 Node.queue_free() 的安全方式释放之前的场景。
SceneTreeTimer create_timer(time_sec: float, process_always: bool = true, process_in_physics: bool = false, ignore_time_scale: bool = false) 🔗
返回一个新的 SceneTreeTimer。在以秒为单位的 time_sec
过去后,该计时器将发出 SceneTreeTimer.timeout 并自动释放。
如果 process_always
为 false
,则当将 paused 设置为 true
时,该计时器将被暂停。
如果 process_in_physics
为 true
,则该计时器将在物理帧结束时,而不是在过程帧结束时更新。
如果 ignore_time_scale
为 true
,则该计时器将忽略 Engine.time_scale 并使用实际的、经过的时间更新。
该方法通常用于创建一次性的延迟计时器,如下例所示:
func some_function():
print("开始")
await get_tree().create_timer(1.0).timeout
print("结束")
public async Task SomeFunction()
{
GD.Print("开始");
await ToSignal(GetTree().CreateTimer(1.0f), SceneTreeTimer.SignalName.Timeout);
GD.Print("结束");
}
注意:该计时器总是在树中的所有节点之后更新。在该计时器更新之前,将调用节点的 Node._process() 方法(如果 process_in_physics
被设置为 true
,则调用 Node._physics_process())。
创建并返回在该树中处理的新的 Tween。该 Tween 将在下一个处理帧或物理帧中自动开始(取决于其 TweenProcessMode)。
注意:使用该方法创建的 Tween 不会被绑定到任何 Node。它可能会继续工作,直到没有任何东西可以进行动画。如果希望在 Node 被释放时自动终结该 Tween,请使用 Node.create_tween() 或 Tween.bind_node()。
Node get_first_node_in_group(group: StringName) 🔗
返回树中找到的第一个加入了 group
分组的 Node,查找时按照场景层次结构顺序。如果没有找到匹配的节点则返回 null
。另见 get_nodes_in_group()。
返回程序开始运行之后已经处理了多少帧。测量的不是经过的时间。
MultiplayerAPI get_multiplayer(for_path: NodePath = NodePath("")) const 🔗
搜索为给定路径配置的 MultiplayerAPI,如果不存在,则会搜索父路径,直到找到为止。如果路径为空,或者没有找到,则返回默认路径。参见 set_multiplayer()。
返回该树中的节点数。
int get_node_count_in_group(group: StringName) const 🔗
返回分配给给定组的节点数。
Array[Node] get_nodes_in_group(group: StringName) 🔗
返回一个 Array,其中包含的是树中所有加入了 group
分组的节点,按照场景层次结构排序。
Array[Tween] get_processed_tweens() 🔗
返回树中当前存在的 Tween 的 Array,包括暂停的补间。
bool has_group(name: StringName) const 🔗
如果树中存在添加到给定组 name
的节点,则返回 true
。
void notify_group(group: StringName, notification: int) 🔗
在树内添加到该 group
的所有节点上,使用给定 notification
调用 Object.notification()。另见 Godot 通知、call_group() 和 set_group()。
注意:该方法立即作用于所有选定的节点,这可能会在某些性能密集型情况下导致卡顿。
void notify_group_flags(call_flags: int, group: StringName, notification: int) 🔗
使用给定的 notification
对添加到 group
的该树内的所有节点调用 Object.notification() 。使用 call_flags
自定义该方法的行为(见 GroupCallFlags)。
void queue_delete(obj: Object) 🔗
将要删除的给定 obj
排队,在当前帧末尾调用其 Object.free()。该方法与 Node.queue_free() 类似。
void quit(exit_code: int = 0) 🔗
在当前迭代结束时使用退出代码 exit_code
退出应用程序。
按照惯例,退出代码 0
表示成功,其他退出代码均表示出错。出于可移植性考虑,退出代码应该在 0
和 125
(含)之间。
注意:这个方法在 iOS 上不起作用。根据 《iOS 人机界面指南》 中的建议,用户应通过 Home 按钮关闭应用程序。
Error reload_current_scene() 🔗
重新加载当前活动的场景,将 current_scene 替换为其原始 PackedScene 的新实例。
成功时返回 @GlobalScope.OK,如果尚未定义 current_scene,则返回 @GlobalScope.ERR_UNCONFIGURED,如果 current_scene 无法加载到 PackedScene 中,则返回 @GlobalScope.ERR_CANT_OPEN,如果场景无法实例化,则返回 @GlobalScope.ERR_CANT_CREATE。
void set_group(group: StringName, property: String, value: Variant) 🔗
将该树内被添加到给定 group
的所有节点上的给定 property
设置为 value
。没有 property
的节点将被忽略。另见 call_group() 和 notify_group()。
注意:该方法立即作用于所有选定的节点上,这可能会在某些性能密集型的情况下导致卡顿。
注意:在 C# 中,在引用 Godot 内置属性时,property
必须是 snake_case。最好使用 PropertyName
类中公开的名称,以避免在每次调用时分配一个新的 StringName。
void set_group_flags(call_flags: int, group: StringName, property: String, value: Variant) 🔗
将该树内被添加到给定 group
的所有节点上的给定 property
设置为 value
。没有 property
的节点将被忽略。使用 call_flags
自定义该方法的行为(请参阅 GroupCallFlags)。
注意:在 C# 中,在引用 Godot 内置方法时,property
必须是 snake_case。最好使用 SignalName
类中公开的名称,以避免在每次调用时分配一个新的 StringName。
void set_multiplayer(multiplayer: MultiplayerAPI, root_path: NodePath = NodePath("")) 🔗
用给定的 root_path
设置自定义的 MultiplayerAPI(同时控制相对的子路径),如果 root_path
为空,则会覆盖默认值。
注意:MultiplayerAPI 不能为包含 root_path
的子路径配置,嵌套的自定义多人游戏是不被允许的。例如,如果为 "/root/Foo"
配置了一项,则为 "/root/Foo/Bar"
设置一项将导致错误。
void unload_current_scene() 🔗
如果当前场景已加载,调用此方法将进行卸载。