Up to date

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

Изменение сцен вручную

Иногда полезно иметь больше контроля над тем, как менять местами сцены. Как упоминалось выше, дочерние узлы Viewport будут рендериться на изображение, которое он генерирует. Это справедливо даже для узлов вне "текущей" сцены. В эту категорию попадают автозагрузки, но также и сцены, которые создаются и добавляются в дерево во время выполнения:

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

func _add_a_scene_manually():
    # This is like autoloading the scene, only
    # it happens after already loading the main scene.
    get_tree().root.add_child(simultaneous_scene)

Для завершения цикла и переключения на новую сцену из старой, разработчики имеют выбор. Существуют много способов для удаления сцены из вида Viewport. Они балансируют между скоростью операций и потреблением памяти а также доступом к данным и целостности.

  1. We can delete the existing scene. SceneTree.change_scene_to_file() and SceneTree.change_scene_to_packed() will delete the current scene immediately. Developers can also delete the main scene though. Assuming the root node's name is "Main", one could do get_node("/root/Main").free() to delete the whole scene.

    • Освобождение памяти.

      • За: в RAM памяти больше нет мёртвого груза.

      • Против: Возврат в эту сцену теперь более затратный так как мы должны снова загрузить её назад в память (занимает время и память). Не проблема если скорый возврат не требуется.

      • Против: Больше нет доступа к данным сцены. Не проблема, если эти данные потребуются не скоро.

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

    • Обработка остановок.

      • За: Нет нод - значит нет обработки, физической обработки, или обработки ввода. Значит что мощности CPU теперь пойдут на выполнение новых задач сцены.

      • Против: Обработка нод и ввода больше не доступна. Не проблема если вас не интересует использование обновлённых данных.

  2. Мы можем скрыть существующую сцену. Изменяя видимость или обнаружение столкновения для нод, мы можем скрыть целую под-древо нод из вида игрока.

    • Память всё ещё существует.

      • За: Вы все еще можете получить доступ к данным если вам нужно.

      • За: Вам больше не нужно перемещать ноды для сохранения данных.

      • Против: Больше данных сохраняются в памяти что влечёт проблемы на чувствительных к проблемам памяти платформах такие как веб или мобильные.

    • Обработка продолжений.

      • За: Данные продолжают получать обновления обработки, так что сцена будет обновлять любые данные внутри себя которые зависят от дельты времени и данных кадра.

      • За: Ноды сохраняются как члены групп (так как группы принадлежат SceneTree).

      • Против: Внимание процессора теперь разделено между обоими сценами. Слишком высокая нагрузка влечёт низкую частоту кадров. Вы должны быть уверены что протестировали производительность так как целевая платформа должна поддерживать то что загружается на ней.

  3. Мы можем удалить существующую сцену из древа. Присвойте значение к существующей ноде в древе сцены. Потом используйте ref:Node.remove_child(Node) <class_Node_method_remove_child> чтобы отсоединить всю сцену от древа.

    • Память все ещё занимается (те же за/против что от скрытия).

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

    • За: Этот вариант "скрытия" намного более лёгок для показа/скрытия. Вместо того чтобы хранить след нескольких изменений в сцене, мы должны только вызвать один метод add/remove_child пары методов. Это то же самое что и отключение игровых объектов в других движках.

    • Против: В отличие от скрытия только от взгляда, данные содержащиеся на сцене станут недоступными если они зависимы от дельты времени, ввода, групп, или других данных которые наследуются от SceneTree.

Также есть места где вам может захотеться иметь множество сцен в одно и то же время. К примеру добавление синглтона во время выполнения, или сохранения данных сцены между изменениями сцены (добавление сцены в корень ноды).

get_tree().root.add_child(scene)

Perhaps instead they wish to display multiple scenes at the same time using SubViewportContainers. This is optimal in cases where the intent is to render different content in different parts of the screen. Minimaps and split-screen multiplayer are good examples.

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