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

Иногда полезно иметь больше контроля над переключением сцен. Дочерние узлы 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. Удаление существующей сцены. SceneTree.change_scene_to_file() и SceneTree.change_scene_to_packed() немедленно удалят текущую сцену. Вы также можете удалить главную сцену вручную. Предполагая, что корневой узел называется "Main", используйте get_node("/root/Main").free() для полного удаления сцены.

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

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

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

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

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

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

      • Преимущество: Отсутствие узлов означает отсутствие обработки, физических расчётов и обработки ввода. ЦПУ освобождается для работы с содержимым новой сцены.

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

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

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

      • Преимущество: при необходимости вы по-прежнему сможете получить доступ к данным.

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

      • Недостаток: больше данных хранится в памяти, что может стать проблемой на чувствительных к памяти платформах, таких как веб-сайты или мобильные устройства.

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

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

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

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

  3. Удаление существующей сцены из дерева. Присвойте переменной корневой узел текущей сцены, затем используйте Node.remove_child(Node) для отсоединения всей сцены от дерева.

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

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

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

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

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

get_tree().root.add_child(scene)

Другим вариантом может быть одновременное отображение нескольких сцен с помощью SubViewportContainers. Это оптимально для отображения разного контента в разных частях экрана (например, мини-карт, многопользовательской игры на разделённом экране).

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