From dbcbceb4bc2abb0068a5e68e4e000ca1bc24fa65 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 11 Jul 2023 01:48:20 +0200 Subject: [PATCH] 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. --- .../autoloads_versus_internal_nodes.rst | 46 ++++----- tutorials/best_practices/data_preferences.rst | 63 ++++++------ tutorials/best_practices/godot_interfaces.rst | 60 +++++------ .../best_practices/godot_notifications.rst | 59 +++++------ .../img/version_control_menu.png | Bin 9915 -> 0 bytes ...ion_control_systems_generate_metadata.webp | Bin 0 -> 2674 bytes tutorials/best_practices/index.rst | 2 - .../introduction_best_practices.rst | 2 - .../best_practices/logic_preferences.rst | 6 +- .../best_practices/node_alternatives.rst | 13 ++- .../best_practices/scene_organization.rst | 10 +- .../best_practices/scenes_versus_scripts.rst | 4 +- .../version_control_systems.rst | 93 ++++++++++++------ .../best_practices/what_are_godot_classes.rst | 12 +-- 14 files changed, 197 insertions(+), 173 deletions(-) delete mode 100644 tutorials/best_practices/img/version_control_menu.png create mode 100644 tutorials/best_practices/img/version_control_systems_generate_metadata.webp diff --git a/tutorials/best_practices/autoloads_versus_internal_nodes.rst b/tutorials/best_practices/autoloads_versus_internal_nodes.rst index 18471ed9f..48664a26a 100644 --- a/tutorials/best_practices/autoloads_versus_internal_nodes.rst +++ b/tutorials/best_practices/autoloads_versus_internal_nodes.rst @@ -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 `. 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 `. 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")``. diff --git a/tutorials/best_practices/data_preferences.rst b/tutorials/best_practices/data_preferences.rst index 4d3a1d16a..1fd202720 100644 --- a/tutorials/best_practices/data_preferences.rst +++ b/tutorials/best_practices/data_preferences.rst @@ -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 `_. + This article makes references to "[something]-time" operations. This + terminology comes from algorithm analysis' + `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 ` would be something like - a ``Vector``. + + 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 ` would be something like + a ``Vector``. 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 diff --git a/tutorials/best_practices/godot_interfaces.rst b/tutorials/best_practices/godot_interfaces.rst index 1540d2dd3..c2a7e0782 100644 --- a/tutorials/best_practices/godot_interfaces.rst +++ b/tutorials/best_practices/godot_interfaces.rst @@ -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 `'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 diff --git a/tutorials/best_practices/godot_notifications.rst b/tutorials/best_practices/godot_notifications.rst index ce8984e89..5e1bdc162 100644 --- a/tutorials/best_practices/godot_notifications.rst +++ b/tutorials/best_practices/godot_notifications.rst @@ -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 `: 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 diff --git a/tutorials/best_practices/img/version_control_menu.png b/tutorials/best_practices/img/version_control_menu.png deleted file mode 100644 index b859bd3ed94f114e11295ef231c6b4f169fa4f72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9915 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 YqLB^`m(Zd9d4r}b4}4c6Yx((q0bpjoNB{r; diff --git a/tutorials/best_practices/img/version_control_systems_generate_metadata.webp b/tutorials/best_practices/img/version_control_systems_generate_metadata.webp new file mode 100644 index 0000000000000000000000000000000000000000..0e236d2553064010dd2d2962d4f097039c48a9c3 GIT binary patch literal 2674 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 literal 0 HcmV?d00001 diff --git a/tutorials/best_practices/index.rst b/tutorials/best_practices/index.rst index 8374571a9..2f5040156 100644 --- a/tutorials/best_practices/index.rst +++ b/tutorials/best_practices/index.rst @@ -1,5 +1,3 @@ -:article_outdated: True - Best practices ============== diff --git a/tutorials/best_practices/introduction_best_practices.rst b/tutorials/best_practices/introduction_best_practices.rst index ec7f37777..349ec01c0 100644 --- a/tutorials/best_practices/introduction_best_practices.rst +++ b/tutorials/best_practices/introduction_best_practices.rst @@ -1,5 +1,3 @@ -:article_outdated: True - .. _doc_introduction_best_practices: Introduction diff --git a/tutorials/best_practices/logic_preferences.rst b/tutorials/best_practices/logic_preferences.rst index 0b98a5caf..b7fa03c91 100644 --- a/tutorials/best_practices/logic_preferences.rst +++ b/tutorials/best_practices/logic_preferences.rst @@ -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 ` 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) ` 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 diff --git a/tutorials/best_practices/node_alternatives.rst b/tutorials/best_practices/node_alternatives.rst index 94a47e53c..6c2d831d7 100644 --- a/tutorials/best_practices/node_alternatives.rst +++ b/tutorials/best_practices/node_alternatives.rst @@ -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 `: Only a little more complex than Object. They track references to themselves, only deleting loaded memory when no diff --git a/tutorials/best_practices/scene_organization.rst b/tutorials/best_practices/scene_organization.rst index 5cf5d367d..1bdd9b371 100644 --- a/tutorials/best_practices/scene_organization.rst +++ b/tutorials/best_practices/scene_organization.rst @@ -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 ` node when it has no child :ref:`CollisionShape2D ` nodes defined. The editor diff --git a/tutorials/best_practices/scenes_versus_scripts.rst b/tutorials/best_practices/scenes_versus_scripts.rst index 77b50cd1a..5e7b892c7 100644 --- a/tutorials/best_practices/scenes_versus_scripts.rst +++ b/tutorials/best_practices/scenes_versus_scripts.rst @@ -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:: diff --git a/tutorials/best_practices/version_control_systems.rst b/tutorials/best_practices/version_control_systems.rst index 8180feb31..8c4a68825 100644 --- a/tutorials/best_practices/version_control_systems.rst +++ b/tutorials/best_practices/version_control_systems.rst @@ -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 `__. Documentation on how to use the Git -plugin can be found -`here `__. +You can find the latest releases on +`GitHub `__. + +Documentation on how to use the Git plugin can be found on its +`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 `__ - 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 ` 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. diff --git a/tutorials/best_practices/what_are_godot_classes.rst b/tutorials/best_practices/what_are_godot_classes.rst index 82e464511..9d6f28efe 100644 --- a/tutorials/best_practices/what_are_godot_classes.rst +++ b/tutorials/best_practices/what_are_godot_classes.rst @@ -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