Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scene unique nodes: clarify intended usage #6670

Merged
merged 6 commits into from
Feb 24, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified tutorials/scripting/img/unique_name.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
81 changes: 68 additions & 13 deletions tutorials/scripting/scene_unique_nodes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,31 @@ Scene Unique Nodes
Introduction
------------

There are times in a project where a node needs to be called
from a script. However, its position in the tree might change
over time as adjustments are made to a scene, such as a
button in a UI scene.
Using ``get_node()`` to reference nodes from a script can sometimes be fragile.
If you move a button in a UI scene from one panel to another, the button's node
path changes, and if a script uses ``get_node()`` with a hard-coded node path,
the script will not be able to find the button anymore.

In situations like this, a node can be turned into a scene
unique node to avoid having to update a script every time
its path is changed.
In situations like this, the node can be turned into a scene
unique node to avoid having to update the script every time
the node's path is changed.

Creating and using them
-----------------------
Creation and usage
------------------

In the Scene tree dock, right-click on a node and select
**Access as Scene Unique Name** in the context menu.
**Access as Unique Name** in the context menu.

.. image:: img/unique_name.png

After checking this, the node will now have a percent symbol (**%**) next
After selecting the option, the node will now have a percent symbol (**%**) next
to its name in the scene tree:

.. image:: img/percent.png

To use a unique node in a script, use the ``%`` symbol and the node's
name in the path for ``get_node()``. For example:
You can now use the node in your script. For example, you can reference it with
a ``get_node()`` method call by typing the % symbol, followed by the node's
name:

.. tabs::

Expand All @@ -41,3 +42,57 @@ name in the path for ``get_node()``. For example:
.. code-tab:: csharp

GetNode<Button>("%RedButton").Text = "Hello";

Same-scene limitation
---------------------

A scene unique node can only be retrieved by a node inside the same scene. To
demonstrate this limitation, consider this example **Player** scene that
instances a **Sword** scene:

.. image:: img/unique_name_scene_instance_example.png

Here are the results of ``get_node()`` calls inside the **Player** script:

- ``get_node("%Eyes")`` returns the **Eyes** node.
- ``get_node("%Hilt")`` returns ``null``.

These are the results of ``get_node()`` calls inside the **Blade** script:

- ``get_node("%Eyes")`` returns ``null``.
- ``get_node("%Hilt")`` returns the **Hilt** node.

If a script has access to a node in another scene, it can call ``get_node()`` on
that node to get scene unique nodes from that node's scene. This also works in a
node path, which avoids multiple ``get_node()`` calls. Here are two ways to get
the **Hilt** node from the **Player** script using scene unique nodes:

- ``get_node("Hand/Sword").get_node("%Hilt")`` returns the **Hilt** node.
- ``get_node("Hand/Sword/%Hilt")`` also returns the **Hilt** node.

Scene unique names don't only work at the end of a node path. They can be used
in the middle to navigate from one node to another. For example, the Sword node
31 marked this conversation as resolved.
Show resolved Hide resolved
is marked as a scene unique node in the **Player** scene, so this is possible:

- ``get_node("%Sword/%Hilt")`` returns the **Hilt** node.

Alternatives
------------

Scene unique nodes are a useful tool to navigate a scene. However, there are
some situations where other techniques may be better.

A :ref:`Group <doc_groups>` allows locating a node (or a group of many nodes)
from any other node, no matter what scene the two nodes are located in.

A :ref:`Singleton (AutoLoad) <doc_singletons_autoload>` is an always loaded node
that can be accessed directly by any node regardless of the scene. These are useful
when some data or functionality is shared globally.

:ref:`Node.find_child() <class_Node_method_find_child>` finds a node by name
without knowing its full path. This seems similar to a scene unique node, but
this method is able to find nodes in nested scenes, and doesn't require marking
the node in the scene editor in any way. However, this method is slow. Scene
unique nodes are cached by Godot and are fast to retrieve, but each time the
method is called, ``find_child()`` needs to check every descendant (every child,
grandchild, and so on).