Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Дерево сцены

Введение

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

"MainLoop"

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

После завершения инициализации, OS должен быть предоставлен MainLoop для запуска. До этого момента все это работало внутри (вы можете проверить файл main/main.cpp в исходном коде, если вам когда-нибудь будет интересно посмотреть, как это работает внутри).

Игра или программа пользователя , запускается в MainLoop. Данный класс имеет несколько методов инициализации, простой (idle) (покадрово-синхронизированный обратный вызов), фиксированный (fixed) (физико-синхронизированный обратный вызов) и ввод (input). Опять же, это низкий уровень, и при создании игр в Godot, написание собственного MainLoop редко имеет смысл.

Дерево сцены

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

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

В любом случае, система сцен обеспечивает собственный основной цикл к ОС, SceneTree. Это автоматически инстанцируется и настраивается при запуске сцены, нет необходимости тратить время на дополнительную работу.

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

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

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

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

Когда узел является частью дерева сцен, SceneTree синглтон (В следующем уроке будет рассмотрен подробнее.) можно получить, просто вызвав Node.get_tree().

Корневое окно

Корневой Viewport всегда находится в верхней части сцены. Из узла его можно получить двумя разными способами:

get_tree().root # Access via scene main loop.
get_node("/root") # Access via absolute path.

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

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

Дерево сцены

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

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

../../_images/activescene.webp

Когда узлы входят в Древо Сцен, они становятся активными. Они получают доступ ко всему, что им нужно для обработки, ввода, отображения 2D и 3D, уведомлений, воспроизведения звука, групп и т.д. Когда они удаляются из древа сцен, они теряют этот доступ.

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

Most node operations in Godot, such as drawing 2D, processing, or getting notifications are done in tree order, or top to bottom as seen in the editor (also known as pre-order traversal):

../../_images/toptobottom.webp

For example, the top node in a scene has its _process() function called first, then the node below it has its _process() function called, then the node below that and so on.

An important exception is the _ready() function: each parent node has its _ready() function called only after all its child nodes have their _ready() functions called, so that the parent knows its children are completely ready to be accessed. This is also known as post-order traversal. In the above image, NameLabel would be notified first (but only after its children, if it had any!), followed by Name, etc., and Panel would be notified last.

The order of operations can also be overridden using the process_priority node property. Nodes with a lower number are called first. For example, nodes with the priorities "0, 1, 2, 3" would be called in that order from left to right.

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

  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 of its descendants.

  3. Every node of the newly added scene will receive the "enter_tree" notification ( _enter_tree() callback in GDScript) in top-to-bottom order (pre-order traversal).

  4. Every node will receive the "ready" notification ( _ready() callback in GDScript) for convenience, once all its children have received the "ready" notification (post-order traversal).

  5. When a scene (or part of it) is removed, they receive the "exit scene" notification ( _exit_tree() callback in GDScript) in bottom-to-top order (the exact reverse of top-to-bottom order).

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

After a scene is loaded, you may want to change this scene for another one. One way to do this is to use the SceneTree.change_scene_to_file() function:

func _my_level_was_completed():
    get_tree().change_scene_to_file("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_packed(PackedScene scene):

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

func _my_level_was_completed():
    get_tree().change_scene_to_packed(next_scene)

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 threaded (background) loading. This must be done manually using Singletons (Autoload) and Фоновая загрузка.