Изменение сцен вручную
Sometimes it helps to have more control over how you swap scenes around. 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, and also scenes which you instantiate and add to the tree at runtime:
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)
public Node simultaneousScene;
public MyClass()
{
simultaneousScene = ResourceLoader.Load<PackedScene>("res://levels/level2.tscn").Instantiate();
}
public void _AddASceneManually()
{
// This is like autoloading the scene, only
// it happens after already loading the main scene.
GetTree().Root.AddChild(simultaneousScene);
}
To complete the cycle and swap out the new scene with the old one, you have a choice to make. Many strategies exist for removing a scene from view of the Viewport. The tradeoffs involve balancing operation speed and memory consumption, as well as balancing data access and integrity.
Удаление существующей сцены. SceneTree.change_scene_to_file() и SceneTree.change_scene_to_packed() немедленно удалят текущую сцену. Вы также можете удалить главную сцену вручную. Предполагая, что корневой узел называется "Main", используйте
get_node("/root/Main").free()для полного удаления сцены.Освобождение памяти.
За: в RAM памяти больше нет мёртвого груза.
Против: Возврат в эту сцену теперь более затратный так как мы должны снова загрузить её назад в память (занимает время и память). Не проблема если скорый возврат не требуется.
Против: Больше нет доступа к данным сцены. Не проблема, если эти данные потребуются не скоро.
Примечание: Может быть полезно сохранить данные из сцены, которая скоро будет удалена, повторно прикрепив один или несколько её узлов к другой сцене или даже напрямую к SceneTree.
Обработка остановок.
Преимущество: Отсутствие узлов означает отсутствие обработки, физических расчётов и обработки ввода. ЦПУ освобождается для работы с содержимым новой сцены.
Недостаток: Обработка и ввод для этих узлов больше не работают. Не проблема, если использование обновленных данных не требуется.
Скрытие существующей сцены. Изменив видимость или обнаружение столкновений узлов, вы можете скрыть всё поддерево узлов от игрока.
Память всё ещё существует.
Pro: You can still access the data if needed.
За: Вам больше не нужно перемещать узлы для сохранения данных.
Con: More data is being kept in memory, which will be become a problem on memory-sensitive platforms like web or mobile.
Обработка продолжений.
Pro: Data continues to receive processing updates, so the scene will keep any data within it that relies on delta time or frame data updated.
За: Узлы сохраняются как члены групп (так как группы принадлежат SceneTree).
Con: The CPU's attention is now divided between both scenes. Too much load could result in low frame rates. You should be sure to test performance as you go to ensure the target platform can support the load from this approach.
Удаление существующей сцены из дерева. Присвойте переменной корневой узел текущей сцены, затем используйте Node.remove_child(Node) для отсоединения всей сцены от дерева.
Memory still exists (similar pros/cons as hiding it from view).
Processing stops (similar pros/cons as deleting it completely).
Pro: This variation of "hiding" it is much easier to show/hide. Rather than potentially keeping track of multiple changes to the scene, you only need to call the add/remove_child methods. This is similar to disabling game objects in other engines.
Против: В отличие от скрытия только от взгляда, данные содержащиеся на сцене станут недоступными если они зависимы от дельты времени, ввода, групп, или других данных которые наследуются от SceneTree.
Также бывают случаи, когда может потребоваться одновременное присутствие нескольких сцен, например, добавление собственного синглтона во время выполнения или сохранение данных сцены между сменой сцен (путём добавления сцены к корневому узлу).
get_tree().root.add_child(scene)
GetTree().Root.AddChild(scene);
Another case may be displaying multiple scenes at the same time using SubViewportContainers. This is optimal for rendering different content in different parts of the screen (e.g. minimaps, split-screen multiplayer).
Each option will have cases where it is best appropriate, so you must examine the effects of each approach, and determine what path best fits your unique situation.