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 的值不会有想要的效果。
bool debug_navigation_hint = false
🔗
如果为 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_mode,它们的 Node._process、Node._physics_process 和 Node._input 回调方法可能不再被调用。
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 并使用实际的、经过的时间更新。
该方法通常用于创建一次性的延迟计时器,如下例所示:
GDScriptC#
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。另见 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() 🔗
如果当前场景已加载,调用此方法将进行卸载。