autoloads_versus_internal_nodes.rst 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. .. _doc_autoloads_versus_internal_nodes:
  2. Autoloads versus regular nodes
  3. ==============================
  4. Godot offers a feature to automatically load nodes at the root of your project,
  5. allowing you to access them globally, that can fulfill the role of a Singleton:
  6. :ref:`doc_singletons_autoload`. These autoloaded nodes are not freed when you
  7. change the scene from code with :ref:`SceneTree.change_scene_to_file <class_SceneTree_method_change_scene_to_file>`.
  8. In this guide, you will learn when to use the Autoload feature, and techniques
  9. you can use to avoid it.
  10. The cutting audio issue
  11. -----------------------
  12. Other engines can encourage the use of creating manager classes, singletons that
  13. organize a lot of functionality into a globally accessible object. Godot offers
  14. many ways to avoid global state thanks to the node tree and signals.
  15. For example, let's say we are building a platformer and want to collect coins
  16. that play a sound effect. There's a node for that: the :ref:`AudioStreamPlayer
  17. <class_AudioStreamPlayer>`. But if we call the ``AudioStreamPlayer`` while it is
  18. already playing a sound, the new sound interrupts the first.
  19. A solution is to code a global, autoloaded sound manager class. It generates a
  20. pool of ``AudioStreamPlayer`` nodes that cycle through as each new request for
  21. sound effects comes in. Say we call that class ``Sound``, you can use it from
  22. anywhere in your project by calling ``Sound.play("coin_pickup.ogg")``. This
  23. solves the problem in the short term but causes more problems:
  24. 1. **Global state**: one object is now responsible for all objects' data. If the
  25. ``Sound`` class has errors or doesn't have an AudioStreamPlayer available,
  26. all the nodes calling it can break.
  27. 2. **Global access**: now that any object can call ``Sound.play(sound_path)``
  28. from anywhere, there's no longer an easy way to find the source of a bug.
  29. 3. **Global resource allocation**: with a pool of ``AudioStreamPlayer`` nodes
  30. stored from the start, you can either have too few and face bugs, or too many
  31. and use more memory than you need.
  32. .. note::
  33. About global access, the problem is that any code anywhere could pass wrong
  34. data to the ``Sound`` autoload in our example. As a result, the domain to
  35. explore to fix the bug spans the entire project.
  36. When you keep code inside a scene, only one or two scripts may be
  37. involved in audio.
  38. Contrast this with each scene keeping as many ``AudioStreamPlayer`` nodes as it
  39. needs within itself and all these problems go away:
  40. 1. Each scene manages its own state information. If there is a problem with the
  41. data, it will only cause issues in that one scene.
  42. 2. Each scene accesses only its own nodes. Now, if there is
  43. a bug, it's easy to find which node is at fault.
  44. 3. Each scene allocates exactly the amount of resources it needs.
  45. Managing shared functionality or data
  46. -------------------------------------
  47. Another reason to use an Autoload can be that you want to reuse the same method
  48. or data across many scenes.
  49. In the case of functions, you can create a new type of ``Node`` that provides
  50. that feature for an individual scene using the :ref:`class_name
  51. <doc_gdscript_basics_class_name>` keyword in GDScript.
  52. When it comes to data, you can either:
  53. 1. Create a new type of :ref:`Resource <class_Resource>` to share the data.
  54. 2. Store the data in an object to which each node has access, for example using
  55. the ``owner`` property to access the scene's root node.
  56. When you should use an Autoload
  57. -------------------------------
  58. GDScript supports the creation of ``static`` functions using ``static func``.
  59. When combined with ``class_name``, this makes it possible to create libraries of
  60. helper functions without having to create an instance to call them. The
  61. limitation of static functions is that they can't reference member variables,
  62. non-static functions or ``self``.
  63. Since Godot 4.1, GDScript also supports ``static`` variables using ``static var``.
  64. This means you can now share variables across instances of a class without
  65. having to create a separate autoload.
  66. Still, autoloaded nodes can simplify your code for systems with a wide scope. If
  67. the autoload is managing its own information and not invading the data of other
  68. objects, then it's a great way to create systems that handle broad-scoped tasks.
  69. For example, a quest or a dialogue system.
  70. .. note::
  71. An autoload is *not* necessarily a singleton. Nothing prevents you from
  72. instantiating copies of an autoloaded node. An autoload is only a tool that
  73. makes a node load automatically as a child of the root of your scene tree,
  74. regardless of your game's node structure or which scene you run, e.g. by
  75. pressing the :kbd:`F6` key.
  76. As a result, you can get the autoloaded node, for example an autoload called
  77. ``Sound``, by calling ``get_node("/root/Sound")``.