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

Sometimes it helps to have more control over how one swaps scenes around. As mentioned above, a Viewport’s child nodes will render to the image it generates. This holds true even for nodes outside of the «current» scene. Autoloads fall into this category, but so do scenes which one instances and adds to the tree at runtime:

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

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

public MyClass()
{
    simultaneousScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
}

public void _AddASceneManually()
{
    // This is like autoloading the scene, only
    // it happens after already loading the main scene.
    GetTree().GetRoot().AddChild(simultaneousScene);
}

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

  1. Мы можем удалить существующую сцену. SceneTree.change_scene() и SceneTree.change_scene_to() немедленно удаляет текущую сцену. Разработчики могут также удалить главную сцену. Если корневая нода имеет имя «Main», то её можно удалить из сцены с помощью get_node("/root/Main").free().

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

      • За: RAM более не мёртвый груз.
      • Против: Возврат в эту сцену теперь более затратный так как мы должны снова загрузить её назад в память (занимает время И память). Не проблема если скорый возврат не требуется.
      • Против: Больше нет доступа к данным сцены. Не проблема если эти данные скоро не потребуются.
      • Заметка: Также пере-подключайте одну или несколько нод в другую сцену или напрямую в SceneTree. Это может быть полезно для сохранения данных сцены которая будет скоро удалена.
    • Обработка остановок.

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

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

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

      • За: Данные продолжают получать обновления обработки, так что сцена будет обновлять любые данные внутри себя которые зависят от дельты времени и данных кадра.
      • За: Ноды сохраняются как члены групп (так как группы принадлежат SceneTree).
      • Против: Внимание процессора теперь разделено между обоими сценами. Слишком высокая нагрузка влечёт низкую частоту кадров. Вы должны быть уверены что протестировали производительность так как целевая платформа должна поддерживать то что загружается на ней.
  3. Мы можем удалить существующую сцену из древа. Присвойте значение к существующей ноде в древе сцены. Потом используйте ref:Node.remove_child(Node) <class_Node_method_remove_child> чтобы отсоединить всю сцену от древа.

    • Memory still exists (similar pros/cons as with hiding it from view).
    • Обработка остановок (те же за/против что и когда мы удаляли их полностью).
    • За: Этот вариант «скрытия» намного более лёгок для показа/скрытия. Вместо того чтобы хранить след нескольких изменений в сцене, мы должны только вызвать один метод add/remove_child пары методов. Это то же самое что и отключение игровых объектов в других движках.
    • Против: В отличие от скрытия только от взгляда, данные содержащиеся на сцене станут недоступными если они зависимы от дельты времени, ввода, групп, или других данных которые наследуются от SceneTree.

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

get_tree().get_root().add_child(scene)
GetTree().GetRoot().AddChild(scene);

Возможно кто-нибудь захочет показать множество сцен в одно и то же время используя ViewportContainers. Это оптимально в случаях когда нужно отрисовать различное содержимое разных частей экрана. Миникарты и разделённые экраны мультиплеера хорошие примеры.

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