SceneTree

介绍

在以前的教程中,所有内容都围绕节点的概念进行。场景是节点的集合。一旦进入 场景树 .

MainLoop

Godot内部工作的方式如下。这里有 OS 类,这是在开始时运行的唯一实例。然后,加载所有驱动程序、服务器、脚本语言、场景系统等。

初始化完成后, OS 需要提供 MainLoop 去跑步。到目前为止,所有这些都是内部工作(如果您有兴趣了解内部工作方式,可以检查源代码中的main/main.cpp文件)。

用户程序或游戏从主循环开始。这个类有几个方法,用于初始化、空闲(帧同步回调)、固定(物理同步回调)和输入。再说一次,这是低级的,在Godot中制作游戏时,编写自己的主循环很少有意义。

SceneTree

解释Godot如何工作的方法之一是,它是一个高级别的游戏引擎,而不是一个低级别的中间件。

场景系统是游戏引擎,而 OS 服务器是低级API。

场景系统为操作系统提供了自己的主循环, SceneTree . 这是在运行场景时自动实例化和设置的,不需要做任何额外的工作。

必须知道这个类的存在,因为它有几个重要的用途:

  • 它包含根 Viewport ,当场景第一次打开成为 场景树 (下一步详细介绍)

  • 它包含有关组的信息,并具有调用组中所有节点或获取组列表的方法。

  • 它包含一些全局状态功能,例如设置暂停模式或退出进程。

当节点是场景树的一部分时, SceneTree 可以通过调用 Node.get_tree() .

根视区

Viewport 总是在场景的顶部。从一个节点,它可以通过两种不同的方式获得:

get_tree().get_root() # Access via scene main loop.
get_node("/root") # Access via absolute path.
GetTree().GetRoot(); // Access via scene main loop.
GetNode("/root"); // Access via absolute path.

此节点包含主视区。任何是一个孩子的 Viewport 默认情况下被绘制到它的内部,因此所有节点的顶部始终是这种类型的节点是有意义的,否则将看不到任何内容。

虽然可以在场景中创建其他视区(用于分割屏幕效果等),但这一个视区是用户从未创建过的唯一视区。它是在scenetree中自动创建的。

场景树

当一个节点直接或间接连接到根视区时,它将成为根视区的一部分。 场景树 .

这意味着,正如前面的教程中所解释的那样,它将得到_enter_tree()和_ready()回调(以及_exit_tree())。

../../_images/activescene.png

当节点进入 场景树 他们变得活跃起来。它们可以访问处理、获取输入、显示二维和三维图像、接收和发送通知、播放声音等所需的所有内容。 场景树 他们失去了这些能力。

树顺序

Godot中的大多数节点操作,如绘图2d、处理或获取通知,都是按树顺序完成的。这意味着树顺序中等级较低的父级和同级将在当前节点之前得到通知。

../../_images/toptobottom.png

通过输入 场景树

  1. 场景从磁盘加载或通过脚本创建。

  2. 场景的根节点(只有一个根,还记得吗?)作为“根”视区(从scenetree)的子视区或其任何子视区或孙子视区添加。

  3. 新添加场景的每个节点都将按从上到下的顺序接收“Enter_Tree”通知(gdscript中的“Enter_Tree()回调)。

  4. 当一个节点及其所有子节点都在活动场景中时,为了方便起见,提供了一个额外的通知“ready”(gdscript中的“ready()回调)。

  5. 当一个场景(或其中的一部分)被删除时,它们会收到从下到上的“退出场景”通知(gdscript中的exit_tree()回调)。

更改当前场景

加载场景后,通常需要将此场景更改为另一个场景。这样做的简单方法是使用 SceneTree.change_scene() 功能:

func _my_level_was_completed():
    get_tree().change_scene("res://levels/level2.tscn")
public void _MyLevelWasCompleted()
{
    GetTree().ChangeScene("res://levels/level2.tscn");
}

与其使用文件路径,还可以使用现成的 PackedScene 使用等效函数的资源 SceneTree.change_scene_to(PackedScene scene)

var next_scene = preload("res://levels/level2.tscn")

func _my_level_was_completed():
    get_tree().change_scene_to(next_scene)
public void _MyLevelWasCompleted()
{
    var nextScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
    GetTree().ChangeSceneTo(nextScene);
}

这些都是快速和有用的方法来切换场景,但缺点是游戏将暂停,直到新的场景被加载和运行。在游戏开发的某个阶段,最好创建适当的加载屏幕,并加载进度条、动画指示器或线程(背景)。这必须使用自动加载(参见下一章)手动完成,并且 后台加载 .