瀏覽代碼

Write nodes_and_scene_instances.rst from scripting_continued.rst

Rewrote the docs
Added an intro section about getting nodes and syntactic sugar
Nathan Lovato 4 年之前
父節點
當前提交
9927bfbb71

+ 0 - 116
getting_started/step_by_step/scripting_continued.rst

@@ -122,122 +122,6 @@ follows, can be applied to nodes:
 As mentioned before, it's better to use these functions instead of
 the notification system.
 
-Creating nodes
---------------
-
-To create a node from code, call the ``.new()`` method, like for any
-other class-based datatype. For example:
-
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    var s
-    func _ready():
-        s = Sprite.new() # Create a new sprite!
-        add_child(s) # Add it as a child of this node.
-
- .. code-tab:: csharp
-
-    private Sprite _sprite;
-
-    public override void _Ready()
-    {
-        base._Ready();
-
-        _sprite = new Sprite(); // Create a new sprite!
-        AddChild(_sprite); // Add it as a child of this node.
-    }
-
-To delete a node, be it inside or outside the scene, ``free()`` must be
-used:
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    func _someaction():
-        s.free() # Immediately removes the node from the scene and frees it.
-
- .. code-tab:: csharp
-
-    public void _SomeAction()
-    {
-        _sprite.Free(); // Immediately removes the node from the scene and frees it.
-    }
-
-When a node is freed, it also frees all its child nodes. Because of
-this, manually deleting nodes is much simpler than it appears. Free
-the base node and everything else in the subtree goes away with it.
-
-A situation might occur where we want to delete a node that
-is currently "blocked", because it is emitting a signal or calling a
-function. This will crash the game. Running Godot
-with the debugger will often catch this case and warn you about it.
-
-The safest way to delete a node is by using
-:ref:`Node.queue_free() <class_Node_method_queue_free>`.
-This erases the node safely during idle.
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    func _someaction():
-        s.queue_free() # Removes the node from the scene and frees it when it becomes safe to do so.
-
- .. code-tab:: csharp
-
-    public void _SomeAction()
-    {
-        _sprite.QueueFree(); // Removes the node from the scene and frees it when it becomes safe to do so.
-    }
-
-Instancing scenes
------------------
-
-Instancing a scene from code is done in two steps. The
-first one is to load the scene from your hard drive:
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    var scene = load("res://myscene.tscn") # Will load when the script is instanced.
-
- .. code-tab:: csharp
-
-    var scene = GD.Load<PackedScene>("res://myscene.tscn"); // Will load when the script is instanced.
-
-
-Preloading it can be more convenient, as it happens at parse
-time (GDScript only):
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    var scene = preload("res://myscene.tscn") # Will load when parsing the script.
-
-But ``scene`` is not yet a node. It's packed in a
-special resource called :ref:`PackedScene <class_PackedScene>`.
-To create the actual node, the function
-:ref:`PackedScene.instance() <class_PackedScene_method_instance>`
-must be called. This will return the tree of nodes that can be added to
-the active scene:
-
-.. tabs::
- .. code-tab:: gdscript GDScript
-
-    var node = scene.instance()
-    add_child(node)
-
- .. code-tab:: csharp
-
-    var node = scene.Instance();
-    AddChild(node);
-
-The advantage of this two-step process is that a packed scene may be
-kept loaded and ready to use so that you can create as many
-instances as desired. This is especially useful to quickly instance
-several enemies, bullets, and other entities in the active scene.
-
 .. _doc_scripting_continued_class_name:
 
 Register scripts as classes

二進制
tutorials/scripting/img/nodes_and_scene_instances_player_scene_example.png


二進制
tutorials/scripting/img/nodes_and_scene_instances_ui_scene_example.png


+ 1 - 0
tutorials/scripting/index.rst

@@ -37,6 +37,7 @@ below will help you make the most of Godot.
    debug/index
    idle_and_physics_processing
    groups
+   nodes_and_scene_instances
    cross_language_scripting
    creating_script_templates
    change_scenes_manually

+ 205 - 0
tutorials/scripting/nodes_and_scene_instances.rst

@@ -0,0 +1,205 @@
+.. _doc_nodes_and_scene_instances:
+
+Nodes and scene instances
+=========================
+
+This guide explains how to get nodes, create nodes, add them as a child, and
+instantiate scenes from code.
+
+Getting nodes
+-------------
+
+You can get a reference to a node by calling the :ref:`Node.get_node()
+<class_Node_method_get_node>` method. For this to work, the child node must be
+present in the scene tree. Getting it in the parent node's ``_ready()`` function
+guarantees that.
+
+Say you have a scene tree like this, and you want to get a reference to the
+Sprite and Camera2D nodes to access them in your script.
+
+.. image:: img/nodes_and_scene_instances_player_scene_example.png
+
+To do so, you can use the following code.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var sprite
+    var camera2d
+
+    func _ready():
+        sprite = get_node("Sprite")
+        camera2d = get_node("Camera2D")
+
+ .. code-tab:: csharp
+
+    private Sprite _sprite;
+    private Camera2D _camera2d;
+
+    public override void _Ready()
+    {
+        base._Ready();
+
+        _sprite = GetNode<Sprite>("Sprite");
+        _camera2d = GetNode<Camera2D>("Camera2D");
+    }
+
+Note that you get nodes by their name. For example, if you rename the Sprite
+node into Skin, the call to get it would have to be ``get_node("Skin")``.
+
+Node paths
+----------
+
+You're not limited to getting a direct child. The ``get_node()`` function
+supports paths, a bit like when working with a file browser. Add a slash to
+separate nodes.
+
+Take the following example scene, with the script attached to the UserInterface
+node.
+
+.. image:: img/nodes_and_scene_instances_ui_scene_example.png
+
+To get the Tween node, you would use the following code.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var tween
+
+    func _ready():
+        tween = get_node("ShieldBar/Tween")
+
+ .. code-tab:: csharp
+
+    private Tween _tween;
+
+    public override void _Ready()
+    {
+        base._Ready();
+
+        _tween = GetNode<Tween>("ShieldBar/Tween");
+    }
+
+.. note:: As with file paths, you can use ".." to get a parent node. The best
+          practice is to avoid doing that though not to break encapsulation and
+          keep your code organized. You can also start the path with a forward
+          slash to make it absolute, in which case your topmost node would be
+          "/root", the application's predefined root viewport.
+
+Syntactic sugar
+~~~~~~~~~~~~~~~
+
+You can use two shorthands to shorten your code in GDScript: putting the
+``onready`` keyword before a member variable makes it initialize right before
+the ``_ready()`` callback.
+
+.. code-block:: gdscript
+
+    onready var sprite = get_node("Sprite")
+
+There is also a short notation for ``get_node()``: the dollar sign, "$". You
+place it before the name or path of the node you want to get.
+
+.. code-block:: gdscript
+
+    onready var sprite = $Sprite
+    onready var tween = $ShieldBar/Tween
+
+Creating nodes
+--------------
+
+To create a node from code, call its ``new()`` method like for any other
+class-based datatype.
+
+You can store the newly created node's reference in a variable and call
+``add_child()`` to add it as a child of the node to which you attached the
+script.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var sprite
+
+    func _ready():
+        var sprite = Sprite.new() # Create a new Sprite.
+        add_child(sprite) # Add it as a child of this node.
+
+ .. code-tab:: csharp
+
+    private Sprite _sprite;
+
+    public override void _Ready()
+    {
+        base._Ready();
+
+        _sprite = new Sprite(); // Create a new Sprite.
+        AddChild(_sprite); // Add it as a child of this node.
+    }
+
+To delete a node and free it from memory, you can call its ``queue_free()``
+method. Doing so queues the node for deletion at the end of the current frame
+after it finished processing. At that point, the engine removes the node from
+the scene and frees the object in memory.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    sprite.queue_free()
+
+ .. code-tab:: csharp
+
+    _sprite.QueueFree();
+
+You can alternatively call ``free()`` to immediately destroy the node. You
+should do this with care as any reference to it will instantly become ``null``.
+We recommend using ``queue_free()`` unless you know what you're doing.
+
+When you free a node, it also frees all its children. Thanks to this, to delete
+an entire branch of the scene tree, you only have to free the topmost parent
+node.
+
+Instancing scenes
+-----------------
+
+Instancing a scene from code happens in two steps:
+
+1. Loading the scene from the hard drive.
+2. Creating an instance of the loaded :ref:`PackedScene <class_PackedScene>`
+   resource.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var scene = load("res://MyScene.tscn")
+
+ .. code-tab:: csharp
+
+    var scene = GD.Load<PackedScene>("res://MyScene.tscn");
+
+Preloading it can improve the user's experience as it happens when parsing the
+script. This feature is only available with GDScript.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var scene = preload("res://MyScene.tscn")
+
+At that point, ``scene`` is a packed scene resource, not a node. To create the
+actual node, you need to call :ref:`PackedScene.instance()
+<class_PackedScene_method_instance>`. It returns a tree of nodes that you can
+add as a child.
+
+.. tabs::
+ .. code-tab:: gdscript GDScript
+
+    var instance = scene.instance()
+    add_child(instance)
+
+ .. code-tab:: csharp
+
+    var instance = scene.();
+    AddChild(instance);
+
+The advantage of this two-step process is you can keep a packed scene loaded and
+create new instances on the fly. For example, to quickly instance several
+enemies or bullets.