mirror of
https://github.com/godotengine/godot-docs.git
synced 2025-12-31 17:49:03 +03:00
Update Best practices documentation for Godot 4.1
Note that the Data preferences page is still marked as outdated, as the internal implementation of Dictionary/HashMap has changed in Godot 4.0.
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_autoloads_versus_internal_nodes:
|
||||
|
||||
Autoloads versus regular nodes
|
||||
@@ -7,7 +5,7 @@ Autoloads versus regular nodes
|
||||
|
||||
Godot offers a feature to automatically load nodes at the root of your project,
|
||||
allowing you to access them globally, that can fulfill the role of a Singleton:
|
||||
:ref:`doc_singletons_autoload`. These auto-loaded nodes are not freed when you
|
||||
:ref:`doc_singletons_autoload`. These autoloaded nodes are not freed when you
|
||||
change the scene from code with :ref:`SceneTree.change_scene_to_file <class_SceneTree_method_change_scene_to_file>`.
|
||||
|
||||
In this guide, you will learn when to use the Autoload feature, and techniques
|
||||
@@ -25,7 +23,7 @@ that play a sound effect. There's a node for that: the :ref:`AudioStreamPlayer
|
||||
<class_AudioStreamPlayer>`. But if we call the ``AudioStreamPlayer`` while it is
|
||||
already playing a sound, the new sound interrupts the first.
|
||||
|
||||
A solution is to code a global, auto-loaded sound manager class. It generates a
|
||||
A solution is to code a global, autoloaded sound manager class. It generates a
|
||||
pool of ``AudioStreamPlayer`` nodes that cycle through as each new request for
|
||||
sound effects comes in. Say we call that class ``Sound``, you can use it from
|
||||
anywhere in your project by calling ``Sound.play("coin_pickup.ogg")``. This
|
||||
@@ -44,7 +42,7 @@ solves the problem in the short term but causes more problems:
|
||||
|
||||
.. note::
|
||||
|
||||
About global access, the problem is that Any code anywhere could pass wrong
|
||||
About global access, the problem is that any code anywhere could pass wrong
|
||||
data to the ``Sound`` autoload in our example. As a result, the domain to
|
||||
explore to fix the bug spans the entire project.
|
||||
|
||||
@@ -82,30 +80,28 @@ When it comes to data, you can either:
|
||||
When you should use an Autoload
|
||||
-------------------------------
|
||||
|
||||
Auto-loaded nodes can simplify your code in some cases:
|
||||
GDScript supports the creation of ``static`` functions using ``static func``.
|
||||
When combined with ``class_name``, this makes it possible to create libraries of
|
||||
helper functions without having to create an instance to call them. The
|
||||
limitation of static functions is that they can't reference member variables,
|
||||
non-static functions or ``self``.
|
||||
|
||||
- **Static Data**: if you need data that is exclusive to one class, like a
|
||||
database, then an autoload can be a good tool. There is no scripting API in
|
||||
Godot to create and manage static data otherwise.
|
||||
Since Godot 4.1, GDScript also supports ``static`` variables using ``static var``.
|
||||
This means you can now share a variables across instances of a class without
|
||||
having to create a separate autoload.
|
||||
|
||||
- **Static functions**: creating a library of functions that only return values.
|
||||
|
||||
- **Systems with a wide scope**: If the singleton is managing its own
|
||||
information and not invading the data of other objects, then it's a great way to
|
||||
create systems that handle broad-scoped tasks. For example, a quest or a
|
||||
dialogue system.
|
||||
|
||||
Until Godot 3.1, another use was just for convenience: autoloads have a global
|
||||
variable for their name generated in GDScript, allowing you to call them from
|
||||
any script file in your project. But now, you can use the ``class_name`` keyword
|
||||
instead to get auto-completion for a type in your entire project.
|
||||
Still, autoloaded nodes can simplify your code for systems with a wide scope. If
|
||||
the autoload is managing its own information and not invading the data of other
|
||||
objects, then it's a great way to create systems that handle broad-scoped tasks.
|
||||
For example, a quest or a dialogue system.
|
||||
|
||||
.. note::
|
||||
|
||||
Autoload is not exactly a Singleton. Nothing prevents you from instantiating
|
||||
copies of an auto-loaded node. It is only a tool that makes a node load
|
||||
automatically as a child of the root of your scene tree, regardless of your
|
||||
game's node structure or which scene you run, e.g. by pressing :kbd:`F6` key.
|
||||
An autoload is *not* necessarily a singleton. Nothing prevents you from
|
||||
instantiating copies of an autoloaded node. An autoload is only a tool that
|
||||
makes a node load automatically as a child of the root of your scene tree,
|
||||
regardless of your game's node structure or which scene you run, e.g. by
|
||||
pressing the :kbd:`F6` key.
|
||||
|
||||
As a result, you can get the auto-loaded node, for example an autoload called
|
||||
As a result, you can get the autoloaded node, for example an autoload called
|
||||
``Sound``, by calling ``get_node("/root/Sound")``.
|
||||
|
||||
@@ -10,33 +10,33 @@ Y or Z? This article covers a variety of topics related to these dilemmas.
|
||||
|
||||
.. note::
|
||||
|
||||
This article makes references to "[something]-time" operations. This
|
||||
terminology comes from algorithm analysis'
|
||||
`Big O Notation <https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/>`_.
|
||||
This article makes references to "[something]-time" operations. This
|
||||
terminology comes from algorithm analysis'
|
||||
`Big O Notation <https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/>`_.
|
||||
|
||||
Long-story short, it describes the worst-case scenario of runtime length.
|
||||
In laymen's terms:
|
||||
Long-story short, it describes the worst-case scenario of runtime length.
|
||||
In laymen's terms:
|
||||
|
||||
"As the size of a problem domain increases, the runtime length of the
|
||||
algorithm..."
|
||||
"As the size of a problem domain increases, the runtime length of the
|
||||
algorithm..."
|
||||
|
||||
- Constant-time, ``O(1)``: "...does not increase."
|
||||
- Logarithmic-time, ``O(log n)``: "...increases at a slow rate."
|
||||
- Linear-time, ``O(n)``: "...increases at the same rate."
|
||||
- Etc.
|
||||
- Constant-time, ``O(1)``: "...does not increase."
|
||||
- Logarithmic-time, ``O(log n)``: "...increases at a slow rate."
|
||||
- Linear-time, ``O(n)``: "...increases at the same rate."
|
||||
- Etc.
|
||||
|
||||
Imagine if one had to process 3 million data points within a single frame. It
|
||||
would be impossible to craft the feature with a linear-time algorithm since
|
||||
the sheer size of the data would increase the runtime far beyond the time allotted.
|
||||
In comparison, using a constant-time algorithm could handle the operation without
|
||||
issue.
|
||||
Imagine if one had to process 3 million data points within a single frame. It
|
||||
would be impossible to craft the feature with a linear-time algorithm since
|
||||
the sheer size of the data would increase the runtime far beyond the time allotted.
|
||||
In comparison, using a constant-time algorithm could handle the operation without
|
||||
issue.
|
||||
|
||||
By and large, developers want to avoid engaging in linear-time operations as
|
||||
much as possible. But, if one keeps the scale of a linear-time operation
|
||||
small, and if one does not need to perform the operation often, then it may
|
||||
be acceptable. Balancing these requirements and choosing the right
|
||||
algorithm / data structure for the job is part of what makes programmers'
|
||||
skills valuable.
|
||||
By and large, developers want to avoid engaging in linear-time operations as
|
||||
much as possible. But, if one keeps the scale of a linear-time operation
|
||||
small, and if one does not need to perform the operation often, then it may
|
||||
be acceptable. Balancing these requirements and choosing the right
|
||||
algorithm / data structure for the job is part of what makes programmers'
|
||||
skills valuable.
|
||||
|
||||
Array vs. Dictionary vs. Object
|
||||
-------------------------------
|
||||
@@ -52,12 +52,13 @@ contents in a contiguous section of memory, i.e. they are in a row adjacent
|
||||
to each other.
|
||||
|
||||
.. note::
|
||||
For those unfamiliar with C++, a Vector is the name of the
|
||||
array object in traditional C++ libraries. It is a "templated"
|
||||
type, meaning that its records can only contain a particular type (denoted
|
||||
by angled brackets). So, for example, a
|
||||
:ref:`PackedStringArray <class_PackedStringArray>` would be something like
|
||||
a ``Vector<String>``.
|
||||
|
||||
For those unfamiliar with C++, a Vector is the name of the
|
||||
array object in traditional C++ libraries. It is a "templated"
|
||||
type, meaning that its records can only contain a particular type (denoted
|
||||
by angled brackets). So, for example, a
|
||||
:ref:`PackedStringArray <class_PackedStringArray>` would be something like
|
||||
a ``Vector<String>``.
|
||||
|
||||
Contiguous memory stores imply the following operation performance:
|
||||
|
||||
@@ -294,7 +295,7 @@ faster than string comparisons (linear-time). If one wants to keep
|
||||
up other languages' conventions though, then one should use integers.
|
||||
|
||||
The primary issue with using integers comes up when one wants to *print*
|
||||
an enum value. As integers, attempting to print MY_ENUM will print
|
||||
an enum value. As integers, attempting to print ``MY_ENUM`` will print
|
||||
``5`` or what-have-you, rather than something like ``"MyEnum"``. To
|
||||
print an integer enum, one would have to write a Dictionary that maps the
|
||||
corresponding string value for each enum.
|
||||
@@ -314,7 +315,7 @@ The answer may not be immediately clear to new Godot users.
|
||||
the engine draws as an animated loop rather than a static image.
|
||||
Users can manipulate...
|
||||
|
||||
1. the rate at which it moves across each section of the texture (fps).
|
||||
1. the rate at which it moves across each section of the texture (FPS).
|
||||
|
||||
2. the number of regions contained within the texture (frames).
|
||||
|
||||
@@ -346,7 +347,7 @@ the AnimatedSprite2D.
|
||||
AnimationPlayers are also the tool one will need to use if they wish to design
|
||||
more complex 2D animation systems, such as...
|
||||
|
||||
1. **Cut-Out animations:** editing sprites' transforms at runtime.
|
||||
1. **Cut-out animations:** editing sprites' transforms at runtime.
|
||||
|
||||
2. **2D Mesh animations:** defining a region for the sprite's texture and
|
||||
rigging a skeleton to it. Then one animates the bones which
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_godot_interfaces:
|
||||
|
||||
Godot interfaces
|
||||
@@ -41,32 +39,36 @@ access.
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
var preres = preload(path) # Load resource during scene load
|
||||
var res = load(path) # Load resource when program reaches statement
|
||||
# If you need an "export const var" (which doesn't exist), use a conditional
|
||||
# setter for a tool script that checks if it's executing in the editor.
|
||||
# The `@tool` annotation must be placed at the top of the script.
|
||||
@tool
|
||||
|
||||
# Load resource during scene load.
|
||||
var preres = preload(path)
|
||||
# Load resource when program reaches statement.
|
||||
var res = load(path)
|
||||
|
||||
# Note that users load scenes and scripts, by convention, with PascalCase
|
||||
# names (like typenames), often into constants.
|
||||
const MyScene : = preload("my_scene.tscn") as PackedScene # Static load
|
||||
const MyScript : = preload("my_script.gd") as Script
|
||||
const MyScene = preload("my_scene.tscn") # Static load
|
||||
const MyScript = preload("my_script.gd")
|
||||
|
||||
# This type's value varies, i.e. it is a variable, so it uses snake_case.
|
||||
export(Script) var script_type: Script
|
||||
|
||||
# If need an "export const var" (which doesn't exist), use a conditional
|
||||
# setter for a tool script that checks if it's executing in the editor.
|
||||
tool # Must place at top of file.
|
||||
@export var script_type: Script
|
||||
|
||||
# Must configure from the editor, defaults to null.
|
||||
export(Script) var const_script setget set_const_script
|
||||
func set_const_script(value):
|
||||
if Engine.is_editor_hint():
|
||||
const_script = value
|
||||
export var const_script: Script:
|
||||
set(value):
|
||||
if Engine.is_editor_hint():
|
||||
const_script = value
|
||||
|
||||
# Warn users if the value hasn't been set.
|
||||
func _get_configuration_warning():
|
||||
func _get_configuration_warnings():
|
||||
if not const_script:
|
||||
return "Must initialize property 'const_script'."
|
||||
return ""
|
||||
return ["Must initialize property 'const_script'."]
|
||||
|
||||
return []
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
@@ -106,7 +108,7 @@ access.
|
||||
};
|
||||
|
||||
// Warn users if the value hasn't been set.
|
||||
public String _GetConfigurationWarning()
|
||||
public String _GetConfigurationWarnings()
|
||||
{
|
||||
if (EnemyScn == null)
|
||||
return "Must initialize property 'EnemyScn'.";
|
||||
@@ -142,7 +144,7 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
print($Child)
|
||||
|
||||
# Fastest. Doesn't break if node moves later.
|
||||
# Note that `@onready` annotation is GDScript only.
|
||||
# Note that `@onready` annotation is GDScript-only.
|
||||
# Other languages must do...
|
||||
# var child
|
||||
# func _ready():
|
||||
@@ -151,6 +153,12 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
func lookup_and_cache_for_future_access():
|
||||
print(child)
|
||||
|
||||
# Fastest. Doesn't break if node is moved in the Scene tree dock.
|
||||
# Node must be selected in the inspector as it's an exported property.
|
||||
@export var child: Node
|
||||
func lookup_and_cache_for_future_access():
|
||||
print(child)
|
||||
|
||||
# Delegate reference assignment to an external source.
|
||||
# Con: need to perform a validation check.
|
||||
# Pro: node makes no requirements of its external structure.
|
||||
@@ -169,8 +177,7 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
return
|
||||
|
||||
# Fail and terminate.
|
||||
# Note: Scripts run from a release export template don't
|
||||
# run `assert` statements.
|
||||
# NOTE: Scripts run from a release export template don't run `assert`s.
|
||||
assert(prop, "'prop' wasn't initialized")
|
||||
|
||||
# Use an autoload.
|
||||
@@ -236,8 +243,7 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
}
|
||||
|
||||
// Fail and terminate.
|
||||
// Note: Scripts run from a release export template don't
|
||||
// run `Debug.Assert` statements.
|
||||
// Note: Scripts run from a release export template don't run `Debug.Assert`s.
|
||||
Debug.Assert(Prop, "'Prop' wasn't initialized");
|
||||
}
|
||||
|
||||
@@ -287,10 +293,8 @@ following checks, in order:
|
||||
execute logic that gives the impression that the Object has a property. This
|
||||
is also the case with the ``_get_property_list`` method.
|
||||
|
||||
- Note that this happens even for non-legal symbol names such as in the
|
||||
case of :ref:`TileSet <class_TileSet>`'s "1/tile_name" property. This
|
||||
refers to the name of the tile with ID 1, i.e.
|
||||
``TileSet.tile_get_name(1)``.
|
||||
- Note that this happens even for non-legal symbol names, such as names
|
||||
starting with a digit or containing a slash.
|
||||
|
||||
As a result, this duck-typed system can locate a property either in the script,
|
||||
the object's class, or any class that object inherits, but only for things
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_godot_notifications:
|
||||
|
||||
Godot notifications
|
||||
@@ -15,17 +13,17 @@ relate to it. For example, if the engine tells a
|
||||
Some of these notifications, like draw, are useful to override in scripts. So
|
||||
much so that Godot exposes many of them with dedicated functions:
|
||||
|
||||
- ``_ready()`` : NOTIFICATION_READY
|
||||
- ``_ready()``: ``NOTIFICATION_READY``
|
||||
|
||||
- ``_enter_tree()`` : NOTIFICATION_ENTER_TREE
|
||||
- ``_enter_tree()``: ``NOTIFICATION_ENTER_TREE``
|
||||
|
||||
- ``_exit_tree()`` : NOTIFICATION_EXIT_TREE
|
||||
- ``_exit_tree()``: ``NOTIFICATION_EXIT_TREE``
|
||||
|
||||
- ``_process(delta)`` : NOTIFICATION_PROCESS
|
||||
- ``_process(delta)``: ``NOTIFICATION_PROCESS``
|
||||
|
||||
- ``_physics_process(delta)`` : NOTIFICATION_PHYSICS_PROCESS
|
||||
- ``_physics_process(delta)``: ``NOTIFICATION_PHYSICS_PROCESS``
|
||||
|
||||
- ``_draw()`` : NOTIFICATION_DRAW
|
||||
- ``_draw()``: ``NOTIFICATION_DRAW``
|
||||
|
||||
What users might *not* realize is that notifications exist for types other
|
||||
than Node alone, for example:
|
||||
@@ -35,7 +33,7 @@ than Node alone, for example:
|
||||
|
||||
- :ref:`Object::NOTIFICATION_PREDELETE <class_Object_constant_NOTIFICATION_PREDELETE>`:
|
||||
a callback that triggers before the engine deletes an Object, i.e. a
|
||||
'destructor'.
|
||||
"destructor".
|
||||
|
||||
And many of the callbacks that *do* exist in Nodes don't have any dedicated
|
||||
methods, but are still quite useful.
|
||||
@@ -48,7 +46,7 @@ methods, but are still quite useful.
|
||||
node.
|
||||
|
||||
One can access all these custom notifications from the universal
|
||||
``_notification`` method.
|
||||
``_notification()`` method.
|
||||
|
||||
.. note::
|
||||
Methods in the documentation labeled as "virtual" are also intended to be
|
||||
@@ -65,38 +63,41 @@ virtual functions?
|
||||
_process vs. _physics_process vs. \*_input
|
||||
------------------------------------------
|
||||
|
||||
Use ``_process`` when one needs a framerate-dependent deltatime between
|
||||
Use ``_process()`` when one needs a framerate-dependent delta time between
|
||||
frames. If code that updates object data needs to update as often as
|
||||
possible, this is the right place. Recurring logic checks and data caching
|
||||
often execute here, but it comes down to the frequency at which one needs
|
||||
the evaluations to update. If they don't need to execute every frame, then
|
||||
implementing a Timer-yield-timeout loop is another option.
|
||||
implementing a Timer-timeout loop is another option.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
# Infinitely loop, but only execute whenever the Timer fires.
|
||||
# Allows for recurring operations that don't trigger script logic
|
||||
# every frame (or even every fixed frame).
|
||||
while true:
|
||||
my_method()
|
||||
$Timer.start()
|
||||
yield($Timer, "timeout")
|
||||
func _ready():
|
||||
var timer = Timer.new()
|
||||
timer.autostart = true
|
||||
timer.wait_time = 0.5
|
||||
add_child(timer)
|
||||
timer.timeout.connect(func():
|
||||
print("This block runs every 0.5 seconds")
|
||||
)
|
||||
|
||||
Use ``_physics_process`` when one needs a framerate-independent deltatime
|
||||
Use ``_physics_process()`` when one needs a framerate-independent delta time
|
||||
between frames. If code needs consistent updates over time, regardless
|
||||
of how fast or slow time advances, this is the right place.
|
||||
Recurring kinematic and object transform operations should execute here.
|
||||
|
||||
While it is possible, to achieve the best performance, one should avoid
|
||||
making input checks during these callbacks. ``_process`` and
|
||||
``_physics_process`` will trigger at every opportunity (they do not "rest" by
|
||||
default). In contrast, ``*_input`` callbacks will trigger only on frames in
|
||||
making input checks during these callbacks. ``_process()`` and
|
||||
``_physics_process()`` will trigger at every opportunity (they do not "rest" by
|
||||
default). In contrast, ``*_input()`` callbacks will trigger only on frames in
|
||||
which the engine has actually detected the input.
|
||||
|
||||
One can check for input actions within the input callbacks just the same.
|
||||
If one wants to use delta time, one can fetch it from the related
|
||||
deltatime methods as needed.
|
||||
delta time methods as needed.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
@@ -146,8 +147,8 @@ _init vs. initialization vs. export
|
||||
|
||||
If the script initializes its own node subtree, without a scene,
|
||||
that code should execute here. Other property or SceneTree-independent
|
||||
initializations should also run here. This triggers before ``_ready`` or
|
||||
``_enter_tree``, but after a script creates and initializes its properties.
|
||||
initializations should also run here. This triggers before ``_ready()`` or
|
||||
``_enter_tree()``, but after a script creates and initializes its properties.
|
||||
|
||||
Scripts have three types of property assignments that can occur during
|
||||
instantiation:
|
||||
@@ -216,16 +217,16 @@ _ready vs. _enter_tree vs. NOTIFICATION_PARENTED
|
||||
------------------------------------------------
|
||||
|
||||
When instantiating a scene connected to the first executed scene, Godot will
|
||||
instantiate nodes down the tree (making ``_init`` calls) and build the tree
|
||||
going downwards from the root. This causes ``_enter_tree`` calls to cascade
|
||||
instantiate nodes down the tree (making ``_init()`` calls) and build the tree
|
||||
going downwards from the root. This causes ``_enter_tree()`` calls to cascade
|
||||
down the tree. Once the tree is complete, leaf nodes call ``_ready``. A node
|
||||
will call this method once all child nodes have finished calling theirs. This
|
||||
then causes a reverse cascade going up back to the tree's root.
|
||||
|
||||
When instantiating a script or a standalone scene, nodes are not
|
||||
added to the SceneTree upon creation, so no ``_enter_tree`` callbacks
|
||||
trigger. Instead, only the ``_init`` call occurs. When the scene is added
|
||||
to the SceneTree, the ``_enter_tree`` and ``_ready`` calls occur.
|
||||
added to the SceneTree upon creation, so no ``_enter_tree()`` callbacks
|
||||
trigger. Instead, only the ``_init()`` call occurs. When the scene is added
|
||||
to the SceneTree, the ``_enter_tree()`` and ``_ready()`` calls occur.
|
||||
|
||||
If one needs to trigger behavior that occurs as nodes parent to another,
|
||||
regardless of whether it occurs as part of the main/active scene or not, one
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
Best practices
|
||||
==============
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_introduction_best_practices:
|
||||
|
||||
Introduction
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_logic_preferences:
|
||||
|
||||
Logic preferences
|
||||
@@ -35,7 +33,7 @@ resources while in the middle of performance-sensitive code.
|
||||
Its counterpart, the :ref:`load <class_@GDScript_method_load>` method, loads a
|
||||
resource only when it reaches the load statement. That is, it will load a
|
||||
resource in-place which can cause slowdowns when it occurs in the middle of
|
||||
sensitive processes. The ``load`` function is also an alias for
|
||||
sensitive processes. The ``load()`` function is also an alias for
|
||||
:ref:`ResourceLoader.load(path) <class_ResourceLoader_method_load>` which is
|
||||
accessible to *all* scripting languages.
|
||||
|
||||
@@ -121,7 +119,7 @@ consider:
|
||||
in exceptional cases, one may wish not to do this:
|
||||
|
||||
1. If the 'imported' class is liable to change, then it should be a property
|
||||
instead, initialized either using an ``export`` or a ``load`` (and
|
||||
instead, initialized either using an ``export`` or a ``load()`` (and
|
||||
perhaps not even initialized until later).
|
||||
|
||||
2. If the script requires a great many dependencies, and one does not wish
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_node_alternatives:
|
||||
|
||||
When and how to avoid using nodes for everything
|
||||
================================================
|
||||
|
||||
|
||||
Nodes are cheap to produce, but even they have their limits. A project may
|
||||
have tens of thousands of nodes all doing things. The more complex their
|
||||
behavior though, the larger the strain each one adds to a project's
|
||||
@@ -30,10 +27,12 @@ your project's features.
|
||||
entire Node library, one creates an abbreviated set of Objects from which
|
||||
a node can generate and manage the appropriate sub-nodes.
|
||||
|
||||
.. note:: One should be careful when handling them. One can store an Object
|
||||
into a variable, but these references can become invalid without warning.
|
||||
For example, if the object's creator decides to delete it out of nowhere,
|
||||
this would trigger an error state when one next accesses it.
|
||||
.. note::
|
||||
|
||||
One should be careful when handling them. One can store an Object
|
||||
into a variable, but these references can become invalid without warning.
|
||||
For example, if the object's creator decides to delete it out of nowhere,
|
||||
this would trigger an error state when one next accesses it.
|
||||
|
||||
2. :ref:`RefCounted <class_RefCounted>`: Only a little more complex than Object.
|
||||
They track references to themselves, only deleting loaded memory when no
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_scene_organization:
|
||||
|
||||
Scene organization
|
||||
@@ -52,7 +50,7 @@ To do this, one must expose data and then rely on a parent context to
|
||||
initialize it:
|
||||
|
||||
1. Connect to a signal. Extremely safe, but should be used only to "respond" to
|
||||
behavior, not start it. Note that signal names are usually past-tense verbs
|
||||
behavior, not start it. By convention, signal names are usually past-tense verbs
|
||||
like "entered", "skill_activated", or "item_collected".
|
||||
|
||||
.. tabs::
|
||||
@@ -219,9 +217,9 @@ in another context without any extra changes to its API.
|
||||
|
||||
To avoid creating and maintaining such documentation, one converts the
|
||||
dependent node ("child" above) into a tool script that implements
|
||||
``_get_configuration_warning()``.
|
||||
Returning a non-empty string from it will make the Scene dock generate a
|
||||
warning icon with the string as a tooltip by the node. This is the same icon
|
||||
``_get_configuration_warnings()``.
|
||||
Returning a non-empty PackedStringArray from it will make the Scene dock generate a
|
||||
warning icon with the string(s) as a tooltip by the node. This is the same icon
|
||||
that appears for nodes such as the
|
||||
:ref:`Area2D <class_Area2D>` node when it has no child
|
||||
:ref:`CollisionShape2D <class_CollisionShape2D>` nodes defined. The editor
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_scenes_versus_scripts:
|
||||
|
||||
When to use scenes versus scripts
|
||||
@@ -202,7 +200,7 @@ In the end, the best approach is to consider the following:
|
||||
security than scripts.
|
||||
|
||||
- If one would like to give a name to a scene, then they can still sort of do
|
||||
this in 3.1 by declaring a script class and giving it a scene as a constant.
|
||||
this by declaring a script class and giving it a scene as a constant.
|
||||
The script becomes, in effect, a namespace:
|
||||
|
||||
.. tabs::
|
||||
|
||||
@@ -1,54 +1,89 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_version_control_systems:
|
||||
|
||||
Version Control Systems
|
||||
Version control systems
|
||||
=======================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Godot aims to be VCS friendly and generate mostly readable and mergeable files.
|
||||
Godot also supports the use of version control systems in the editor itself.
|
||||
However, VCS in the editor requires a plugin for the specific VCS you are using.
|
||||
VCS can be setup or shut down in the editor under **Project > Version Control**.
|
||||
Godot aims to be VCS-friendly and generate mostly readable and mergeable files.
|
||||
|
||||
.. image:: img/version_control_menu.png
|
||||
Version control plugins
|
||||
-----------------------
|
||||
|
||||
Godot also supports the use of version control systems in the editor itself.
|
||||
However, version control in the editor requires a plugin for the specific VCS
|
||||
you're using.
|
||||
|
||||
As of July 2023, there is only a Git plugin available, but the community may
|
||||
create additional VCS plugins.
|
||||
|
||||
Official Git plugin
|
||||
-------------------
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
|
||||
As of July 2023, the Git plugin hasn't been updated to work with Godot 4.1
|
||||
and later yet.
|
||||
|
||||
Using Git from inside the editor is supported with an official plugin.
|
||||
You can find the latest releases
|
||||
`here <https://github.com/godotengine/godot-git-plugin/releases>`__. Documentation on how to use the Git
|
||||
plugin can be found
|
||||
`here <https://github.com/godotengine/godot-git-plugin/wiki>`__.
|
||||
You can find the latest releases on
|
||||
`GitHub <https://github.com/godotengine/godot-git-plugin/releases>`__.
|
||||
|
||||
Documentation on how to use the Git plugin can be found on its
|
||||
`wiki <https://github.com/godotengine/godot-git-plugin/wiki>`__.
|
||||
|
||||
Files to exclude from VCS
|
||||
-------------------------
|
||||
|
||||
There are some files and folders Godot automatically creates. You should add them to your VCS ignore:
|
||||
.. note::
|
||||
|
||||
- ``.godot/``: This folder stores various project cache data. ``.godot/imported/`` stores
|
||||
all the files the engine imports automatically based on your source assets and their
|
||||
import flags. ``.godot/editor/`` holds data regarding the editor state, such as currently
|
||||
opened script files, and recently used nodes.
|
||||
- ``*.translation``: These files are binary imported translations generated from CSV files.
|
||||
- ``export_presets.cfg``: This file contains all the export presets for the
|
||||
project, including sensitive information such as Android keystore credentials.
|
||||
- ``.mono/``: This folder stores automatically-generated Mono files. It only exists
|
||||
in projects that use the Mono version of Godot.
|
||||
This lists files and folders that should be ignored from version control in
|
||||
Godot 4.1 and later.
|
||||
|
||||
.. tip::
|
||||
The list of files of folders that should be ignored from version control in
|
||||
Godot 3.x and Godot 4.0 is **entirely** different. This is important, as Godot
|
||||
3.x and 4.0 may store sensitive credentials in ``export_presets.cfg`` (unlike Godot
|
||||
4.1 and later).
|
||||
|
||||
Save `this .gitignore file <https://raw.githubusercontent.com/github/gitignore/master/Godot.gitignore>`__
|
||||
in your project's root folder to set up file exclusions automatically.
|
||||
If you are using Godot 3, check the ``3.5`` version of this documentation page
|
||||
instead.
|
||||
|
||||
There are some files and folders Godot automatically creates when opening a
|
||||
project in the editor for the first time. To avoid bloating your version control
|
||||
repository with generated data, you should add them to your VCS ignore:
|
||||
|
||||
- ``.godot/``: This folder stores various project cache data.
|
||||
- ``*.translation``: These files are binary imported
|
||||
:ref:`translations <doc_internationalizing_games>` generated from CSV files.
|
||||
|
||||
You can make the Godot project manager generate version control metadata for you
|
||||
automatically when creating a project. When choosing the **Git** option, this
|
||||
creates ``.gitignore`` and ``.gitattributes`` files in the project root:
|
||||
|
||||
.. figure:: img/version_control_systems_generate_metadata.webp
|
||||
:align: center
|
||||
:alt: Creating version control metadata in the project manager's New Project dialog
|
||||
|
||||
Creating version control metadata in the project manager's **New Project** dialog
|
||||
|
||||
In existing projects, select the **Project** menu at the top of the editor, then
|
||||
choose **Version Control > Generate Version Control Metadata**. This creates the
|
||||
same files as if the operation was performed in the project manager.
|
||||
|
||||
Working with Git on Windows
|
||||
---------------------------
|
||||
|
||||
Most Git for Windows clients are configured with the ``core.autocrlf`` set to ``true``.
|
||||
This can lead to files unnecessarily being marked as modified by Git due to their line endings being converted automatically.
|
||||
It is better to set this option as::
|
||||
Most Git for Windows clients are configured with the ``core.autocrlf`` set to
|
||||
``true``. This can lead to files unnecessarily being marked as modified by Git
|
||||
due to their line endings being converted from LF to CRLF automatically.
|
||||
|
||||
It is better to set this option as:
|
||||
|
||||
::
|
||||
|
||||
git config --global core.autocrlf input
|
||||
|
||||
Creating version control metadata using the project manager or editor will
|
||||
automatically enforce LF line endings using the ``.gitattributes`` file.
|
||||
In this case, you don't need to change your Git configuration.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_what_are_godot_classes:
|
||||
|
||||
Applying object-oriented principles in Godot
|
||||
@@ -54,15 +52,15 @@ The behavior of scenes has many similarities to classes, so it can make sense to
|
||||
a class. Scenes are reusable, instantiable, and inheritable groups of nodes. Creating a scene is
|
||||
similar to having a script that creates nodes and adds them as children using ``add_child()``.
|
||||
|
||||
We often pair a scene with a scripted root node that makes use of the scene's nodes. As such,
|
||||
We often pair a scene with a scripted root node that makes use of the scene's nodes. As such,
|
||||
the script extends the scene by adding behavior through imperative code.
|
||||
|
||||
The content of a scene helps to define:
|
||||
|
||||
- What nodes are available to the script
|
||||
- How they are organized
|
||||
- How they are initialized
|
||||
- What signal connections they have with each other
|
||||
- What nodes are available to the script.
|
||||
- How they are organized.
|
||||
- How they are initialized.
|
||||
- What signal connections they have with each other.
|
||||
|
||||
Why is any of this important to scene organization? Because instances of scenes *are* objects. As a
|
||||
result, many object-oriented principles that apply to written code also apply to scenes: single
|
||||
|
||||
Reference in New Issue
Block a user