Дерево сцены

Введение

In previous tutorials, everything revolved around the concept of nodes. Scenes are collections of nodes. They become active once they enter the scene tree.

«MainLoop»

То, как Godot работает внутри, выглядит следующим образом. Существует класс OS, который является единственным экземпляром, запускаемым в самом начале. После этого загружаются все драйверы, серверы, скриптовые языки, система сцен и т.д.

When initialization is complete, OS needs to be supplied a MainLoop to run. Up to this point, all this is internals working (you can check main/main.cpp file in the source code if you are ever interested to see how this works internally).

The user program, or game, starts in the MainLoop. This class has a few methods, for initialization, idle (frame-synchronized callback), fixed (physics-synchronized callback), and input. Again, this is low level and when making games in Godot, writing your own MainLoop seldom makes sense.

Дерево сцены

Один из способов объяснить, как работает Godot, звучит так: это высокоуровневый игровой движок над низкоуровневым промежуточным ПО.

Система сцены является игровым движком, в то время как OS и сервера являются API низкого уровня.

The scene system provides its own main loop to OS, SceneTree. This is automatically instanced and set when running a scene, no need to do any extra work.

Важно знать, о существовании этого класса, так как он имеет несколько важных применений:

  • Он содержит корневой Viewport, к которому сцена добавляется как дочерняя, когда она впервые открывается то становится частью древа сцен (подробнее об этом ниже)
  • Он содержит информацию о группах и позволяет вызывать все узлы в группе или получать список этих узлов.
  • Он содержит некоторые глобальные функции состояния, такие как режим паузы или выход.

When a node is part of the Scene Tree, the SceneTree singleton can be obtained by calling 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.

This node contains the main viewport. Anything that is a child of a Viewport is drawn inside of it by default, so it makes sense that the top of all nodes is always a node of this type otherwise nothing would be seen.

В то время как в сцене могут быть созданы другие видовые окна (для эффекта раздельного экрана и т.д.), это единственное окно, которое никогда не создается пользователем. Он создается автоматически внутри SceneTree.

Дерево сцены

Когда узел прямо или косвенно связан с корневым окном, он становится частью дерева сцены.

Это означает, что, как объяснялось в предыдущих уроках, он получит обратные вызовы _enter_tree() и _ready(), (а также _exit_tree()).

../../_images/activescene.png

When nodes enter the Scene Tree, they become active. They get access to everything they need to process, get input, display 2D and 3D visuals, receive and send notifications, play sounds, etc. When they are removed from the scene tree, they lose these abilities.

Последовательность в древе

Most node operations in Godot, such as drawing 2D, processing, or getting notifications are done in tree order. This means that parents and siblings with a lower rank in the tree order will get notified before the current node.

../../_images/toptobottom.png

«Становится активным», войдя в Древо Сцен

  1. Сцена загружается с диска или создается с помощью скрипта.
  2. The root node of that scene (only one root, remember?) is added as either a child of the «root» Viewport (from SceneTree), or to any child or grandchild of it.
  3. Каждый узел новой добавленной сцены получит уведомление «enter_tree» (обратный вызов _enter_tree() в GDScript) в порядке сверху вниз.
  4. Дополнительное уведомление, «ready» (обратный вызов _ready() в GDScript ), предоставляется для удобства, когда узел и все его дети находятся внутри активной сцены.
  5. Когда сцена (или ее часть) удалена, они получают уведомление «exit scene» (обратный вызов _exit_tree() в GDScript) в порядке снизу вверх

Смена текущей сцены

After a scene is loaded, it is often desired to change this scene for another one. The simple way to do this is to use the SceneTree.change_scene() function:

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

Rather than using file paths, one can also use ready-made PackedScene resources using the equivalent function 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);
}

These are quick and useful ways to switch scenes but have the drawback that the game will stall until the new scene is loaded and running. At some point in the development of your game, it may be preferable to create proper loading screens with progress bar, animated indicators or thread (background) loading. This must be done manually using autoloads (see next chapter) and Background loading.