浏览代码

Added 'Changing scenes manually' section

Will Nations 6 年之前
父节点
当前提交
b1efd097de
共有 3 个文件被更改,包括 163 次插入2 次删除
  1. 23 2
      getting_started/step_by_step/scene_tree.rst
  2. 139 0
      tutorials/misc/change_scenes_manually.rst
  3. 1 0
      tutorials/misc/index.rst

+ 23 - 2
getting_started/step_by_step/scene_tree.rst

@@ -158,9 +158,30 @@ function:
         GetTree().ChangeScene("res://levels/level2.tscn");
         GetTree().ChangeScene("res://levels/level2.tscn");
     }
     }
 
 
-This is a quick and useful way to switch scenes but has the drawback
+Rather than using file paths, one can also use ready-made
+:ref:`PackedScene <class_PackedScene>` resources using the equivalent
+function
+:ref:`SceneTree.change_scene_to(PackedScene scene) <class_SceneTree_change_scene_to>`:
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var next_scene = preload("res://levels/level2.tscn")
+
+    func _my_level_was_completed():
+    	get_tree().change_scene_to(next_scene)
+
+ .. code-tab:: csharp
+
+    public void _MyLevelWasCompleted()
+    {
+        PackedScene nextScene = ResourceLoader.load("res://levels/level2.tscn") as PackedScene;
+        GetTree().ChangeSceneTo(nextScene);
+    }
+
+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
 that the game will stall until the new scene is loaded and running. At
 some point in your game, it may be desired to create proper loading
 some point in your game, it may be desired to create proper loading
 screens with progress bar, animated indicators or thread (background)
 screens with progress bar, animated indicators or thread (background)
 loading. This must be done manually using autoloads (see next chapter!)
 loading. This must be done manually using autoloads (see next chapter!)
-and :ref:`doc_background_loading`.
+and :ref:`doc_background_loading`.

+ 139 - 0
tutorials/misc/change_scenes_manually.rst

@@ -0,0 +1,139 @@
+.. _doc_change_scenes_manually:
+
+Change scenes manually
+======================
+
+Sometimes it helps to have more control over how one swaps scenes around.
+As mentioned above, a :ref:`Viewport <class_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:
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    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)
+
+ .. code-tab:: csharp
+
+    public PackedScene simultaneousScene;
+
+    public MyClass()
+    {
+        simultaneousScene = ResourceLoader.load("res://levels/level2.tscn") as PackedScene;
+    }
+
+    public void _AddASceneManually()
+    {
+        // this is like autoloading the scene, only
+        // it happens after already loading the main scene.
+        GetTree().GetRoot().AddChild(simultaneousScene);
+    }
+
+To complete the cycle and swap out the new scene with the old one,
+developers have a choice to make. Many strategies exist for removing a scene
+from view of the :ref:`Viewport <class_Viewport>`. The tradeoffs involve
+balancing operation speed and memory consumption as well as balancing data
+access and integrity.
+
+1. **We can delete the existing scene.**
+:ref:`SceneTree.change_scene/_to <class_SceneTree_change_scene>` 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.
+
+    - Unloads memory.
+    
+        - Pro: RAM is no longer dragging the dead weight.
+
+        - Con: Returning to that scene is now more expensive since it must be
+          loaded back into memory again (takes time AND memory). Not a problem
+          if returning soon is unnecessary.
+
+        - Con: No longer have access to that scene's data. Not a problem if
+          using that data soon is unnecessary.
+
+        - Note: It can be useful to preserve the data in a soon-to-be-deleted
+          scene by re-attaching one or more of its nodes to a different scene,
+          or even directly to the :ref:`SceneTree <class_SceneTree>`.
+
+    - Processing stops.
+
+        - Pro: No nodes means no process, physics process, or input
+          handling. The CPU is available to work on the new scene's contents.
+
+        - Con: Those nodes' processing and input handling no longer operate.
+          Not a problem if using the updated data is unnecessary.
+
+2. **We can hide the existing scene.** By changing the visibility or collision
+   detection of the nodes, we can hide the entire node sub-tree from the
+   player's perspective.
+
+    - Memory still exists.
+
+        - Pro: One can still access the data if need be.
+
+        - Pro: There's no need to move any more nodes around to save data.
+
+        - Con: More data is being kept in memory which will be become a problem
+          on memory-sensitive platforms like web or mobile.
+
+    - Processing continues.
+
+        - Pro: Data continues to receive processing updates, so the scene will
+          keep updated any data within it that relies on delta time or frame
+          data.
+
+        - Pro: Nodes are still members of groups (since groups belong to the 
+          :ref:`SceneTree <class_SceneTree>`).
+
+        - Con: The CPU's attention is now divided between both scenes. Too much
+          load could result in low frame rates. One should be sure to test 
+          performance as they go to ensure the target platform can support the
+          load they are giving it.
+
+3. **We can remove the existing scene from the tree.** Assign a variable
+   to the existing scene's root node. Then use
+   :ref:`Node.remove_child(Node) <class_Node_remove_child>` to detach the entire
+   scene from the tree.
+
+    - Memory still exists (similar pros/cons as with hiding it from view).
+
+    - Processing stops (similar pros/cons as with 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, one
+      must only call the one method add/remove_child pair of methods. It is
+      similar to disabling game objects in other engines.
+
+    - Con: Unlike with hiding it from view only, the data contained within
+      the scene will become stale if it relies on delta time, input, groups,
+      or other data that is derived from :ref:`SceneTree <class_SceneTree>`
+      access.
+
+There are also cases where one may wish to have many scenes present at the same
+time. Perhaps one is adding their own singleton at runtime, or preserving a
+a scene's data between scene changes (adding the scene to the root node).
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+        get_tree().get_root().add_child(scene)
+
+ .. code-tab:: csharp
+
+        GetTree().GetRoot().AddChild(scene);
+
+Perhaps instead they wish to display multiple scenes at the same time using a
+:ref:`ViewportContainers <class_ViewportContainer>`. 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.
+
+Each option will have cases where it is best appropriate, so one must
+examine the effects of each and determine what path best fits 
+their unique situation.

+ 1 - 0
tutorials/misc/index.rst

@@ -9,3 +9,4 @@ Miscellaneous
    pausing_games
    pausing_games
    binary_serialization_api
    binary_serialization_api
    running_code_in_the_editor
    running_code_in_the_editor
+   change_scenes_manually