Move remaining files out of step_by_step/

Moved those to scripting/:

- filesystem
- resources
- singletons_autoload
- scene_tree

export to export/

and godot_design_philosophy to introduction/
This commit is contained in:
Nathan Lovato
2020-12-02 19:13:33 -06:00
parent 96637f2d5b
commit d0eb1eb6bc
46 changed files with 18 additions and 15 deletions

Binary file not shown.

View File

@@ -0,0 +1,111 @@
.. _doc_filesystem:
File system
===========
Introduction
------------
A file system manages how assets are stored and how they are accessed.
A well-designed file system also allows multiple developers to edit the
same source files and assets while collaborating. Godot stores
all assets as files in its file system.
Implementation
--------------
The file system stores resources on disk. Anything, from a script, to a scene or a
PNG image is a resource to the engine. If a resource contains properties
that reference other resources on disk, the paths to those resources are also
included. If a resource has sub-resources that are built-in, the resource is
saved in a single file together with all the bundled sub-resources. For
example, a font resource is often bundled together with the font textures.
The Godot file system avoids using metadata files. Existing asset managers and VCSs
are better than anything we can implement, so Godot tries its best to play along
with SVN, Git, Mercurial, Perforce, etc.
Example of file system contents:
.. code-block:: none
/project.godot
/enemy/enemy.tscn
/enemy/enemy.gd
/enemy/enemysprite.png
/player/player.gd
project.godot
-------------
The ``project.godot`` file is the project description file, and it is always found
at the root of the project. In fact, its location defines where the root is. This
is the first file that Godot looks for when opening a project.
This file contains the project configuration in plain text, using the win.ini
format. Even an empty ``project.godot`` can function as a basic definition of
a blank project.
Path delimiter
--------------
Godot only supports ``/`` as a path delimiter. This is done for
portability reasons. All operating systems support this, even Windows,
so a path such as ``C:\project\project.godot`` needs to be typed as
``C:/project/project.godot``.
Resource path
-------------
When accessing resources, using the host OS file system layout can be
cumbersome and non-portable. To solve this problem, the special path
``res://`` was created.
The path ``res://`` will always point at the project root (where
``project.godot`` is located, so ``res://project.godot`` is always
valid).
This file system is read-write only when running the project locally from
the editor. When exported or when running on different devices (such as
phones or consoles, or running from DVD), the file system will become
read-only and writing will no longer be permitted.
User path
---------
Writing to disk is still needed for tasks such as saving game state or
downloading content packs. To this end, the engine ensures that there is a
special path ``user://`` that is always writable. This path resolves
differently depending on the OS the project is running on. Local path
resolution is further explained in :ref:`doc_data_paths`.
Host file system
----------------
Alternatively host file system paths can also be used, but this is not recommended
for a released product as these paths are not guaranteed to work on all platforms.
However, using host file system paths can be useful when writing development
tools in Godot.
Drawbacks
---------
There are some drawbacks to this simple file system design. The first issue is that
moving assets around (renaming them or moving them from one path to another inside
the project) will break existing references to these assets. These references will
have to be re-defined to point at the new asset location.
To avoid this, do all your move, delete and rename operations from within Godot, on
the FileSystem dock. Never move assets from outside Godot, or dependencies will have
to be fixed manually (Godot detects this and helps you fix them anyway, but why
go the hard route?).
The second is that, under Windows and macOS, file and path names are case insensitive.
If a developer working in a case insensitive host file system saves an asset as ``myfile.PNG``,
but then references it as ``myfile.png``, it will work fine on their platform, but not
on other platforms, such as Linux, Android, etc. This may also apply to exported binaries,
which use a compressed package to store all files.
It is recommended that your team clearly define a naming convention for files when
working with Godot. One simple fool-proof convention is to only allow lowercase
file and path names.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -30,6 +30,8 @@ Some features are specific to the engine and are available in all supported
languages. Whether you code in GDScript, C#, or another language, the pages
below will help you make the most of Godot.
.. To split and organize better, into some related toctrees?
.. toctree::
:maxdepth: 1
:name: toc-scripting-core-features
@@ -45,3 +47,7 @@ below will help you make the most of Godot.
change_scenes_manually
instancing_with_signals
pausing_games
filesystem
resources
singletons_autoload
scene_tree

View File

@@ -0,0 +1,368 @@
.. _doc_resources:
Resources
=========
Nodes and resources
-------------------
Up to this tutorial, we focused on the :ref:`Node <class_Node>`
class in Godot as that's the one you use to code behavior and
most of the engine's features rely on it. There is
another datatype that is just as important:
:ref:`Resource <class_Resource>`.
*Nodes* give you functionality: they draw sprites, 3D models, simulate physics,
arrange user interfaces, etc. **Resources** are **data containers**. They don't
do anything on their own: instead, nodes use the data contained in resources.
Anything Godot saves or loads from disk is a resource. Be it a scene (a ``.tscn``
or an ``.scn`` file), an image, a script... Here are some ``Resource`` examples:
:ref:`Texture <class_Texture>`, :ref:`Script <class_Script>`, :ref:`Mesh
<class_Mesh>`, :ref:`Animation <class_Animation>`, :ref:`AudioStream
<class_AudioStream>`, :ref:`Font <class_Font>`, :ref:`Translation
<class_Translation>`.
When the engine loads a resource from disk, **it only loads it once**. If a copy
of that resource is already in memory, trying to load the resource again will
return the same copy every time. As resources only contain data, there is no need
to duplicate them.
Every object, be it a Node or a Resource, can export properties. There are many
types of Properties, like String, integer, Vector2, etc., and any of these types
can become a resource. This means that both nodes and resources can contain
resources as properties:
.. image:: img/nodes_resources.png
External vs built-in
--------------------
There are two ways to save resources. They can be:
1. **External** to a scene, saved on the disk as individual files.
2. **Built-in**, saved inside the ``.tscn`` or the ``.scn`` file they're attached to.
To be more specific, here's a :ref:`Texture <class_Texture>`
in a :ref:`Sprite <class_Sprite>` node:
.. image:: img/spriteprop.png
Clicking the resource preview allows us to view and edit the resource's properties.
.. image:: img/resourcerobi.png
The path property tells us where the resource comes from. In this case, it comes
from a PNG image called ``robi.png``. When the resource comes from a file like
this, it is an external resource. If you erase the path or this path is empty,
it becomes a built-in resource.
The switch between built-in and external resources happens when you save the
scene. In the example above, if you erase the path ``"res://robi.png"`` and
save, Godot will save the image inside the ``.tscn`` scene file.
.. note::
Even if you save a built-in resource, when you instance a scene multiple
times, the engine will only load one copy of it.
Loading resources from code
---------------------------
There are two ways to load resources from code. First, you can use the ``load()`` function anytime:
.. tabs::
.. code-tab:: gdscript GDScript
func _ready():
var res = load("res://robi.png") # Godot loads the Resource when it reads the line.
get_node("sprite").texture = res
.. code-tab:: csharp
public override void _Ready()
{
var texture = (Texture)GD.Load("res://robi.png"); // Godot loads the Resource when it reads the line.
var sprite = (Sprite)GetNode("sprite");
sprite.Texture = texture;
}
You can also ``preload`` resources. Unlike ``load``, this function will read the
file from disk and load it at compile-time. As a result, you cannot call preload
with a variable path: you need to use a constant string.
.. tabs::
.. code-tab:: gdscript GDScript
func _ready():
var res = preload("res://robi.png") # Godot loads the resource at compile-time
get_node("sprite").texture = res
.. code-tab:: csharp
// 'preload()' is unavailable in C Sharp.
Loading scenes
--------------
Scenes are also resources, but there is a catch. Scenes saved to disk are
resources of type :ref:`PackedScene <class_PackedScene>`. The
scene is packed inside a resource.
To get an instance of the scene, you have to use the
:ref:`PackedScene.instance() <class_PackedScene_method_instance>` method.
.. tabs::
.. code-tab:: gdscript GDScript
func _on_shoot():
var bullet = preload("res://bullet.tscn").instance()
add_child(bullet)
.. code-tab:: csharp
private PackedScene _bulletScene = (PackedScene)GD.Load("res://bullet.tscn");
public void OnShoot()
{
Node bullet = _bulletScene.Instance();
AddChild(bullet);
}
This method creates the nodes in the scene's hierarchy, configures them, and
returns the root node of the scene. You can then add it as a child of any other
node.
The approach has several advantages. As the :ref:`PackedScene.instance()
<class_PackedScene_method_instance>` function is fast, you can create new
enemies, bullets, effects, etc. without having to load them again from disk each
time. Remember that, as always, images, meshes, etc. are all shared between the
scene instances.
Freeing resources
-----------------
When a ``Resource`` is no longer in use, it will automatically free itself.
Since, in most cases, Resources are contained in Nodes, when you free a node,
the engine frees all the resources it owns as well if no other node uses them.
Creating your own resources
---------------------------
Like any Object in Godot, users can also script Resources. Resource scripts
inherit the ability to freely translate between object properties and serialized
text or binary data (\*.tres, \*.res). They also inherit the reference-counting
memory management from the Reference type.
This comes with many distinct advantages over alternative data
structures, such as JSON, CSV, or custom TXT files. Users can only import these
assets as a :ref:`Dictionary <class_Dictionary>` (JSON) or as a
:ref:`File <class_File>` to parse. What sets Resources apart is their
inheritance of :ref:`Object <class_Object>`, :ref:`Reference <class_Reference>`,
and :ref:`Resource <class_Resource>` features:
- They can define constants, so constants from other data fields or objects are not needed.
- They can define methods, including setter/getter methods for properties. This allows for abstraction and encapsulation of the underlying data. If the Resource script's structure needs to change, the game using the Resource need not also change.
- They can define signals, so Resources can trigger responses to changes in the data they manage.
- They have defined properties, so users know 100% that their data will exist.
- Resource auto-serialization and deserialization is a built-in Godot Engine feature. Users do not need to implement custom logic to import/export a resource file's data.
- Resources can even serialize sub-Resources recursively, meaning users can design even more sophisticated data structures.
- Users can save Resources as version-control-friendly text files (\*.tres). Upon exporting a game, Godot serializes resource files as binary files (\*.res) for increased speed and compression.
- Godot Engine's Inspector renders and edits Resource files out-of-the-box. As such, users often do not need to implement custom logic to visualize or edit their data. To do so, double-click the resource file in the FileSystem dock or click the folder icon in the Inspector and open the file in the dialog.
- They can extend **other** resource types besides just the base Resource.
Godot makes it easy to create custom Resources in the Inspector.
1. Create a plain Resource object in the Inspector. This can even be a type that derives Resource, so long as your script is extending that type.
2. Set the ``script`` property in the Inspector to be your script.
The Inspector will now display your Resource script's custom properties. If one edits
those values and saves the resource, the Inspector serializes the custom properties
too! To save a resource from the Inspector, click the Inspector's tools menu (top right),
and select "Save" or "Save As...".
If the script's language supports :ref:`script classes <doc_gdscript_basics_class_name>`,
then it streamlines the process. Defining a name for your script alone will add it to
the Inspector's creation dialog. This will auto-add your script to the Resource
object you create.
Let's see some examples.
.. tabs::
.. code-tab:: gdscript GDScript
# bot_stats.gd
extends Resource
export(int) var health
export(Resource) var sub_resource
export(Array, String) var strings
func _init(p_health = 0, p_sub_resource = null, p_strings = []):
health = p_health
sub_resource = p_sub_resource
strings = p_strings
# bot.gd
extends KinematicBody
export(Resource) var stats
func _ready():
# Uses an implicit, duck-typed interface for any 'health'-compatible resources.
if stats:
print(stats.health) # Prints '10'.
.. code-tab:: csharp
// BotStats.cs
using System;
using Godot;
namespace ExampleProject {
public class BotStats : Resource
{
[Export]
public int Health { get; set; }
[Export]
public Resource SubResource { get; set; }
[Export]
public String[] Strings { get; set; }
public BotStats(int health = 0, Resource subResource = null, String[] strings = null)
{
Health = health;
SubResource = subResource;
Strings = strings ?? new String[0];
}
}
}
// Bot.cs
using System;
using Godot;
namespace ExampleProject {
public class Bot : KinematicBody
{
[Export]
public Resource Stats;
public override void _Ready()
{
if (Stats != null && Stats is BotStats botStats) {
GD.Print(botStats.Health); // Prints '10'.
}
}
}
}
.. note::
Resource scripts are similar to Unity's ScriptableObjects. The Inspector
provides built-in support for custom resources. If desired though, users
can even design their own Control-based tool scripts and combine them
with an :ref:`EditorPlugin <class_EditorPlugin>` to create custom
visualizations and editors for their data.
Unreal Engine 4's DataTables and CurveTables are also easy to recreate with
Resource scripts. DataTables are a String mapped to a custom struct, similar
to a Dictionary mapping a String to a secondary custom Resource script.
.. tabs::
.. code-tab:: gdscript GDScript
# bot_stats_table.gd
extends Resource
const BotStats = preload("bot_stats.gd")
var data = {
"GodotBot": BotStats.new(10), # Creates instance with 10 health.
"DifferentBot": BotStats.new(20) # A different one with 20 health.
}
func _init():
print(data)
.. code-tab:: csharp
using System;
using Godot;
public class BotStatsTable : Resource
{
private Godot.Dictionary<String, BotStats> _stats = new Godot.Dictionary<String, BotStats>();
public BotStatsTable()
{
_stats["GodotBot"] = new BotStats(10); // Creates instance with 10 health.
_stats["DifferentBot"] = new BotStats(20); // A different one with 20 health.
GD.Print(_stats);
}
}
Instead of just inlining the Dictionary values, one could also, alternatively...
1. Import a table of values from a spreadsheet and generate these key-value pairs, or...
2. Design a visualization within the editor and create a simple plugin that adds it
to the Inspector when you open these types of Resources.
CurveTables are the same thing, except mapped to an Array of float values
or a :ref:`Curve <class_Curve>`/:ref:`Curve2D <class_Curve2D>` resource object.
.. warning::
Beware that resource files (\*.tres/\*.res) will store the path of the script
they use in the file. When loaded, they will fetch and load this script as an
extension of their type. This means that trying to assign a subclass, i.e. an
inner class of a script (such as using the ``class`` keyword in GDScript) won't
work. Godot will not serialize the custom properties on the script subclass properly.
In the example below, Godot would load the ``Node`` script, see that it doesn't
extend ``Resource``, and then determine that the script failed to load for the
Resource object since the types are incompatible.
.. tabs::
.. code-tab:: gdscript GDScript
extends Node
class MyResource:
extends Resource
export var value = 5
func _ready():
var my_res = MyResource.new()
# This will NOT serialize the 'value' property.
ResourceSaver.save("res://my_res.tres", my_res)
.. code-tab:: csharp
using System;
using Godot;
public class MyNode : Node
{
public class MyResource : Resource
{
[Export]
public int Value { get; set; } = 5;
}
public override void _Ready()
{
var res = new MyResource();
// This will NOT serialize the 'Value' property.
ResourceSaver.Save("res://MyRes.tres", res);
}
}

View File

@@ -0,0 +1,179 @@
.. _doc_scene_tree:
SceneTree
=========
Introduction
------------
In previous tutorials, everything revolved around the concept of
nodes. Scenes are collections of nodes. They become active once
they enter the *scene tree*.
MainLoop
--------
The way Godot works internally is as follows. There is the
:ref:`OS <class_OS>` class,
which is the only instance that runs at the beginning. Afterwards, all
drivers, servers, scripting languages, scene system, etc are loaded.
When initialization is complete, :ref:`OS <class_OS>` needs to be
supplied a :ref:`MainLoop <class_MainLoop>`
to run. Up to this point, all this is internals working (you can check
main/main.cpp file in the source code if you are ever interested to
see how this works internally).
The user program, or game, starts in the MainLoop. This class has a few
methods, for initialization, idle (frame-synchronized callback), fixed
(physics-synchronized callback), and input. Again, this is low
level and when making games in Godot, writing your own MainLoop seldom makes sense.
SceneTree
---------
One of the ways to explain how Godot works is that it's a high level
game engine over a low level middleware.
The scene system is the game engine, while the :ref:`OS <class_OS>`
and servers are the low level API.
The scene system provides its own main loop to OS,
:ref:`SceneTree <class_SceneTree>`.
This is automatically instanced and set when running a scene, no need
to do any extra work.
It's important to know that this class exists because it has a few
important uses:
- It contains the root :ref:`Viewport <class_Viewport>`, to which a
scene is added as a child when it's first opened to become
part of the *Scene Tree* (more on that next).
- It contains information about the groups and has the means to call all
nodes in a group or get a list of them.
- It contains some global state functionality, such as setting pause
mode or quitting the process.
When a node is part of the Scene Tree, the
:ref:`SceneTree <class_SceneTree>`
singleton can be obtained by calling
:ref:`Node.get_tree() <class_Node_method_get_tree>`.
Root viewport
-------------
The root :ref:`Viewport <class_Viewport>`
is always at the top of the scene. From a node, it can be obtained in
two different ways:
.. tabs::
.. code-tab:: gdscript GDScript
get_tree().get_root() # Access via scene main loop.
get_node("/root") # Access via absolute path.
.. code-tab:: csharp
GetTree().GetRoot(); // Access via scene main loop.
GetNode("/root"); // Access via absolute path.
This node contains the main viewport. Anything that is a child of a
:ref:`Viewport <class_Viewport>`
is drawn inside of it by default, so it makes sense that the top of all
nodes is always a node of this type otherwise nothing would be seen.
While other viewports can be created in the scene (for split-screen
effects and such), this one is the only one that is never created by the
user. It's created automatically inside SceneTree.
Scene tree
----------
When a node is connected, directly or indirectly, to the root
viewport, it becomes part of the *scene tree*.
This means that as explained in previous tutorials, it will get the
_enter_tree() and _ready() callbacks (as well as _exit_tree()).
.. image:: img/activescene.png
When nodes enter the *Scene Tree*, they become active. They get access
to everything they need to process, get input, display 2D and 3D visuals,
receive and send notifications, play sounds, etc. When they are removed from the
*scene tree*, they lose these abilities.
Tree order
----------
Most node operations in Godot, such as drawing 2D, processing, or getting
notifications are done in tree order. This means that parents and
siblings with a lower rank in the tree order will get notified before
the current node.
.. image:: img/toptobottom.png
"Becoming active" by entering the *Scene Tree*
----------------------------------------------
#. A scene is loaded from disk or created by scripting.
#. The root node of that scene (only one root, remember?) is added as
either a child of the "root" Viewport (from SceneTree), or to any
of its descendants.
#. Every node of the newly added scene, will receive the "enter_tree"
notification ( ``_enter_tree()`` callback in GDScript) in
top-to-bottom order.
#. An extra notification, "ready" ( ``_ready()`` callback in GDScript)
is provided for convenience, when a node and all its children are
inside the active scene.
#. When a scene (or part of it) is removed, they receive the "exit
scene" notification ( ``_exit_tree()`` callback in GDScript) in
bottom-to-top order
Changing current scene
----------------------
After a scene is loaded, it is often desired to change this scene for
another one. The simple way to do this is to use the
:ref:`SceneTree.change_scene() <class_SceneTree_method_change_scene>`
function:
.. tabs::
.. code-tab:: gdscript GDScript
func _my_level_was_completed():
get_tree().change_scene("res://levels/level2.tscn")
.. code-tab:: csharp
public void _MyLevelWasCompleted()
{
GetTree().ChangeScene("res://levels/level2.tscn");
}
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_method_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()
{
var nextScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
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
some point in the development of your game, it may be preferable to create proper loading
screens with progress bar, animated indicators or thread (background)
loading. This must be done manually using autoloads (see next chapter)
and :ref:`doc_background_loading`.

View File

@@ -0,0 +1,293 @@
.. _doc_singletons_autoload:
Singletons (AutoLoad)
=====================
Introduction
------------
Godot's scene system, while powerful and flexible, has a drawback: there is no
method for storing information (e.g. a player's score or inventory) that is
needed by more than one scene.
It's possible to address this with some workarounds, but they come with their
own limitations:
- You can use a "master" scene that loads and unloads other scenes as
its children. However, this means you can no longer run those scenes
individually and expect them to work correctly.
- Information can be stored to disk in ``user://`` and then loaded by scenes
that require it, but frequently saving and loading data is cumbersome and
may be slow.
The `Singleton pattern <https://en.wikipedia.org/wiki/Singleton_pattern>`_ is
a useful tool for solving the common use case where you need to store
persistent information between scenes. In our case, it's possible to reuse the
same scene or class for multiple singletons as long as they have different
names.
Using this concept, you can create objects that:
- Are always loaded, no matter which scene is currently running.
- Can store global variables such as player information.
- Can handle switching scenes and between-scene transitions.
- *Act* like a singleton, since GDScript does not support global variables by design.
Autoloading nodes and scripts can give us these characteristics.
.. note::
Godot won't make an AutoLoad a "true" singleton as per the singleton design
pattern. It may still be instanced more than once by the user if desired.
AutoLoad
--------
You can create an AutoLoad to load a scene or a script that inherits from
:ref:`class_Node`.
.. note::
When autoloading a script, a :ref:`class_Node` will be created and the script will be
attached to it. This node will be added to the root viewport before any
other scenes are loaded.
.. image:: img/singleton.png
To autoload a scene or script, select **Project > Project Settings** from the
menu and switch to the **AutoLoad** tab.
.. image:: img/autoload_tab.png
Here you can add any number of scenes or scripts. Each entry in the list
requires a name, which is assigned as the node's ``name`` property. The order of
the entries as they are added to the global scene tree can be manipulated using
the up/down arrow keys.
.. image:: img/autoload_example.png
This means that any node can access a singleton named "PlayerVariables" with:
.. tabs::
.. code-tab:: gdscript GDScript
var player_vars = get_node("/root/PlayerVariables")
player_vars.health -= 10
.. code-tab:: csharp
var playerVariables = (PlayerVariables)GetNode("/root/PlayerVariables");
playerVariables.Health -= 10; // Instance field.
If the **Enable** column is checked (which is the default), then the singleton can
be accessed directly without requiring ``get_node()``:
.. tabs::
.. code-tab:: gdscript GDScript
PlayerVariables.health -= 10
.. code-tab:: csharp
// Static members can be accessed by using the class name.
PlayerVariables.Health -= 10;
Note that autoload objects (scripts and/or scenes) are accessed just like any
other node in the scene tree. In fact, if you look at the running scene tree,
you'll see the autoloaded nodes appear:
.. image:: img/autoload_runtime.png
Custom scene switcher
---------------------
This tutorial will demonstrate building a scene switcher using autoloads.
For basic scene switching, you can use the
:ref:`SceneTree.change_scene() <class_SceneTree_method_change_scene>`
method (see :ref:`doc_scene_tree` for details). However, if you need more
complex behavior when changing scenes, this method provides more functionality.
To begin, download the template from here:
:download:`autoload.zip <files/autoload.zip>` and open it in Godot.
The project contains two scenes: ``Scene1.tscn`` and ``Scene2.tscn``. Each
scene contains a label displaying the scene name and a button with its
``pressed()`` signal connected. When you run the project, it starts in
``Scene1.tscn``. However, pressing the button does nothing.
Global.gd
~~~~~~~~~
Switch to the **Script** tab and create a new script called ``Global.gd``.
Make sure it inherits from ``Node``:
.. image:: img/autoload_script.png
The next step is to add this script to the autoLoad list. Open
**Project > Project Settings** from the menu, switch to the **AutoLoad** tab and
select the script by clicking the browse button or typing its path:
``res://Global.gd``. Press **Add** to add it to the autoload list:
.. image:: img/autoload_tutorial1.png
Now whenever we run any scene in the project, this script will always be loaded.
Returning to the script, it needs to fetch the current scene in the
`_ready()` function. Both the current scene (the one with the button) and
``Global.gd`` are children of root, but autoloaded nodes are always first. This
means that the last child of root is always the loaded scene.
.. tabs::
.. code-tab:: gdscript GDScript
extends Node
var current_scene = null
func _ready():
var root = get_tree().get_root()
current_scene = root.get_child(root.get_child_count() - 1)
.. code-tab:: csharp
using Godot;
using System;
public class Global : Godot.Node
{
public Node CurrentScene { get; set; }
public override void _Ready()
{
Viewport root = GetTree().GetRoot();
CurrentScene = root.GetChild(root.GetChildCount() - 1);
}
}
Now we need a function for changing the scene. This function needs to free the
current scene and replace it with the requested one.
.. tabs::
.. code-tab:: gdscript GDScript
func goto_scene(path):
# This function will usually be called from a signal callback,
# or some other function in the current scene.
# Deleting the current scene at this point is
# a bad idea, because it may still be executing code.
# This will result in a crash or unexpected behavior.
# The solution is to defer the load to a later time, when
# we can be sure that no code from the current scene is running:
call_deferred("_deferred_goto_scene", path)
func _deferred_goto_scene(path):
# It is now safe to remove the current scene
current_scene.free()
# Load the new scene.
var s = ResourceLoader.load(path)
# Instance the new scene.
current_scene = s.instance()
# Add it to the active scene, as child of root.
get_tree().get_root().add_child(current_scene)
# Optionally, to make it compatible with the SceneTree.change_scene() API.
get_tree().set_current_scene(current_scene)
.. code-tab:: csharp
public void GotoScene(string path)
{
// This function will usually be called from a signal callback,
// or some other function from the current scene.
// Deleting the current scene at this point is
// a bad idea, because it may still be executing code.
// This will result in a crash or unexpected behavior.
// The solution is to defer the load to a later time, when
// we can be sure that no code from the current scene is running:
CallDeferred(nameof(DeferredGotoScene), path);
}
public void DeferredGotoScene(string path)
{
// It is now safe to remove the current scene
CurrentScene.Free();
// Load a new scene.
var nextScene = (PackedScene)GD.Load(path);
// Instance the new scene.
CurrentScene = nextScene.Instance();
// Add it to the active scene, as child of root.
GetTree().GetRoot().AddChild(CurrentScene);
// Optionally, to make it compatible with the SceneTree.change_scene() API.
GetTree().SetCurrentScene(CurrentScene);
}
Using :ref:`Object.call_deferred() <class_Object_method_call_deferred>`,
the second function will only run once all code from the current scene has
completed. Thus, the current scene will not be removed while it is
still being used (i.e. its code is still running).
Finally, we need to fill the empty callback functions in the two scenes:
.. tabs::
.. code-tab:: gdscript GDScript
# Add to 'Scene1.gd'.
func _on_Button_pressed():
Global.goto_scene("res://Scene2.tscn")
.. code-tab:: csharp
// Add to 'Scene1.cs'.
public void OnButtonPressed()
{
var global = (Global)GetNode("/root/Global");
global.GotoScene("res://Scene2.tscn");
}
and
.. tabs::
.. code-tab:: gdscript GDScript
# Add to 'Scene2.gd'.
func _on_Button_pressed():
Global.goto_scene("res://Scene1.tscn")
.. code-tab:: csharp
// Add to 'Scene2.cs'.
public void OnButtonPressed()
{
var global = (Global)GetNode("/root/Global");
global.GotoScene("res://Scene1.tscn");
}
Run the project and test that you can switch between scenes by pressing
the button.
.. note::
When scenes are small, the transition is instantaneous. However, if your
scenes are more complex, they may take a noticeable amount of time to appear.
To learn how to handle this, see the next tutorial: :ref:`doc_background_loading`.
Alternatively, if the loading time is relatively short (less than 3 seconds or so),
you can display a "loading plaque" by showing some kind of 2D element just before
changing the scene. You can then hide it just after the scene is changed. This can
be used to indicate to the player that a scene is being loaded.