resources.rst 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. .. _doc_resources:
  2. Resources
  3. =========
  4. Nodes and resources
  5. -------------------
  6. Up to this tutorial, we focused on the :ref:`Node <class_Node>`
  7. class in Godot as that's the one you use to code behavior and
  8. most of the engine's features rely on it. There is
  9. another datatype that is just as important:
  10. :ref:`Resource <class_Resource>`.
  11. *Nodes* give you functionality: they draw sprites, 3D models, simulate physics,
  12. arrange user interfaces, etc. **Resources** are **data containers**. They don't
  13. do anything on their own: instead, nodes use the data contained in resources.
  14. Anything Godot saves or loads from disk is a resource. Be it a scene (a ``.tscn``
  15. or an ``.scn`` file), an image, a script... Here are some :ref:`Resource <class_Resource>` examples:
  16. - :ref:`Texture <class_Texture>`
  17. - :ref:`Script <class_Script>`
  18. - :ref:`Mesh <class_Mesh>`
  19. - :ref:`Animation <class_Animation>`
  20. - :ref:`AudioStream <class_AudioStream>`
  21. - :ref:`Font <class_Font>`
  22. - :ref:`Translation <class_Translation>`
  23. When the engine loads a resource from disk, **it only loads it once**. If a copy
  24. of that resource is already in memory, trying to load the resource again will
  25. return the same copy every time. As resources only contain data, there is no need
  26. to duplicate them.
  27. Every object, be it a Node or a Resource, can export properties. There are many
  28. types of Properties, like String, integer, Vector2, etc., and any of these types
  29. can become a resource. This means that both nodes and resources can contain
  30. resources as properties:
  31. .. image:: img/nodes_resources.webp
  32. External vs built-in
  33. --------------------
  34. There are two ways to save resources. They can be:
  35. 1. **External** to a scene, saved on the disk as individual files.
  36. 2. **Built-in**, saved inside the ``.tscn`` or the ``.scn`` file they're attached to.
  37. To be more specific, here's a :ref:`Texture2D <class_Texture2D>`
  38. in a :ref:`Sprite2D <class_Sprite2D>` node:
  39. .. image:: img/spriteprop.webp
  40. Clicking the resource preview allows us to view the resource's properties.
  41. .. image:: img/resourcerobi.webp
  42. The path property tells us where the resource comes from. In this case, it comes
  43. from a PNG image called ``robi.png``. When the resource comes from a file like
  44. this, it is an external resource. If you erase the path or this path is empty,
  45. it becomes a built-in resource.
  46. The switch between built-in and external resources happens when you save the
  47. scene. In the example above, if you erase the path ``"res://robi.png"`` and
  48. save, Godot will save the image inside the ``.tscn`` scene file.
  49. .. note::
  50. Even if you save a built-in resource, when you instance a scene multiple
  51. times, the engine will only load one copy of it.
  52. Loading resources from code
  53. ---------------------------
  54. There are two ways to load resources from code. First, you can use the ``load()`` function anytime:
  55. .. tabs::
  56. .. code-tab:: gdscript GDScript
  57. func _ready():
  58. # Godot loads the Resource when it reads this very line.
  59. var imported_resource = load("res://robi.png")
  60. $sprite.texture = imported_resource
  61. .. code-tab:: csharp
  62. public override void _Ready()
  63. {
  64. // Godot loads the Resource when it executes this line.
  65. var texture = GD.Load<Texture>("res://Robi.png");
  66. var sprite = GetNode<Sprite2D>("sprite");
  67. sprite.Texture = texture;
  68. }
  69. You can also ``preload`` resources. Unlike ``load``, this function will read the
  70. file from disk and load it at compile-time. As a result, you cannot call ``preload``
  71. with a variable path: you need to use a constant string.
  72. .. tabs::
  73. .. code-tab:: gdscript GDScript
  74. func _ready():
  75. # Godot loads the resource at compile-time
  76. var imported_resource = preload("res://robi.png")
  77. get_node("sprite").texture = imported_resource
  78. .. code-tab:: csharp
  79. // 'preload()' is unavailable in C Sharp.
  80. Loading scenes
  81. --------------
  82. Scenes are also resources, but there is a catch. Scenes saved to disk are
  83. resources of type :ref:`PackedScene <class_PackedScene>`. The
  84. scene is packed inside a :ref:`Resource <class_Resource>`.
  85. To get an instance of the scene, you have to use the
  86. :ref:`PackedScene.instantiate() <class_PackedScene_method_instantiate>` method.
  87. .. tabs::
  88. .. code-tab:: gdscript GDScript
  89. func _on_shoot():
  90. var bullet = preload("res://bullet.tscn").instantiate()
  91. add_child(bullet)
  92. .. code-tab:: csharp
  93. private PackedScene _bulletScene = GD.Load<PackedScene>("res://Bullet.tscn");
  94. private void OnShoot()
  95. {
  96. Node bullet = _bulletScene.Instantiate();
  97. AddChild(bullet);
  98. }
  99. This method creates the nodes in the scene's hierarchy, configures them, and
  100. returns the root node of the scene. You can then add it as a child of any other
  101. node.
  102. The approach has several advantages. As the :ref:`PackedScene.instantiate()
  103. <class_PackedScene_method_instantiate>` function is fast, you can create new
  104. enemies, bullets, effects, etc. without having to load them again from disk each
  105. time. Remember that, as always, images, meshes, etc. are all shared between the
  106. scene instances.
  107. Freeing resources
  108. -----------------
  109. When a :ref:`Resource <class_Resource>` is no longer in use, it will automatically free itself.
  110. Since, in most cases, Resources are contained in Nodes, when you free a node,
  111. the engine frees all the resources it owns as well if no other node uses them.
  112. Creating your own resources
  113. ---------------------------
  114. Like any Object in Godot, users can also script Resources. Resource scripts
  115. inherit the ability to freely translate between object properties and serialized
  116. text or binary data (\*.tres, \*.res). They also inherit the reference-counting
  117. memory management from the RefCounted type.
  118. This comes with many distinct advantages over alternative data
  119. structures, such as JSON, CSV, or custom TXT files. Users can only import these
  120. assets as a :ref:`Dictionary <class_Dictionary>` (JSON) or as a
  121. :ref:`FileAccess <class_FileAccess>` to parse. What sets Resources apart is their
  122. inheritance of :ref:`Object <class_Object>`, :ref:`RefCounted <class_RefCounted>`,
  123. and :ref:`Resource <class_Resource>` features:
  124. - They can define constants, so constants from other data fields or objects are not needed.
  125. - 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.
  126. - They can define signals, so Resources can trigger responses to changes in the data they manage.
  127. - They have defined properties, so users know 100% that their data will exist.
  128. - 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.
  129. - Resources can even serialize sub-Resources recursively, meaning users can design even more sophisticated data structures.
  130. - 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.
  131. - 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.
  132. - They can extend **other** resource types besides just the base Resource.
  133. Godot makes it easy to create custom Resources in the Inspector.
  134. 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.
  135. 2. Set the ``script`` property in the Inspector to be your script.
  136. The Inspector will now display your Resource script's custom properties. If one edits
  137. those values and saves the resource, the Inspector serializes the custom properties
  138. too! To save a resource from the Inspector, click the Inspector's tools menu (top right),
  139. and select "Save" or "Save As...".
  140. If the script's language supports :ref:`script classes <doc_gdscript_basics_class_name>`,
  141. then it streamlines the process. Defining a name for your script alone will add it to
  142. the Inspector's creation dialog. This will auto-add your script to the Resource
  143. object you create.
  144. Let's see some examples.
  145. Create a :ref:`Resource <class_Resource>` and name it ``bot_stats``.
  146. It should appear in your file tab with the full name ``bot_stats.tres``.
  147. Without a script, it's useless, so let's add some data and logic!
  148. Attach a script to it named ``bot_stats.gd`` (or just create a new script, and then drag it to it).
  149. .. note::
  150. If you're using C#, you need to annotate your Resource class with the ``[GlobalClass]`` attribute for it to show up in the create resource GUI.
  151. .. tabs::
  152. .. code-tab:: gdscript GDScript
  153. extends Resource
  154. @export var health: int
  155. @export var sub_resource: Resource
  156. @export var strings: PackedStringArray
  157. # Make sure that every parameter has a default value.
  158. # Otherwise, there will be problems with creating and editing
  159. # your resource via the inspector.
  160. func _init(p_health = 0, p_sub_resource = null, p_strings = []):
  161. health = p_health
  162. sub_resource = p_sub_resource
  163. strings = p_strings
  164. .. code-tab:: csharp
  165. // BotStats.cs
  166. using Godot;
  167. namespace ExampleProject
  168. {
  169. [GlobalClass]
  170. public partial class BotStats : Resource
  171. {
  172. [Export]
  173. public int Health { get; set; }
  174. [Export]
  175. public Resource SubResource { get; set; }
  176. [Export]
  177. public string[] Strings { get; set; }
  178. // Make sure you provide a parameterless constructor.
  179. // In C#, a parameterless constructor is different from a
  180. // constructor with all default values.
  181. // Without a parameterless constructor, Godot will have problems
  182. // creating and editing your resource via the inspector.
  183. public BotStats() : this(0, null, null) {}
  184. public BotStats(int health, Resource subResource, string[] strings)
  185. {
  186. Health = health;
  187. SubResource = subResource;
  188. Strings = strings ?? System.Array.Empty<string>();
  189. }
  190. }
  191. }
  192. Now, create a :ref:`CharacterBody3D <class_CharacterBody3D>`, name it ``Bot``, and add the following script to it:
  193. .. tabs::
  194. .. code-tab:: gdscript GDScript
  195. extends CharacterBody3D
  196. @export var stats: Resource
  197. func _ready():
  198. # Uses an implicit, duck-typed interface for any 'health'-compatible resources.
  199. if stats:
  200. stats.health = 10
  201. print(stats.health)
  202. # Prints "10"
  203. .. code-tab:: csharp
  204. // Bot.cs
  205. using Godot;
  206. namespace ExampleProject
  207. {
  208. public partial class Bot : CharacterBody3D
  209. {
  210. [Export]
  211. public Resource Stats;
  212. public override void _Ready()
  213. {
  214. if (Stats is BotStats botStats)
  215. {
  216. GD.Print(botStats.Health); // Prints '10'.
  217. }
  218. }
  219. }
  220. }
  221. Now, select the :ref:`CharacterBody3D <class_CharacterBody3D>` node which we named ``bot``, and drag&drop the ``bot_stats.tres`` resource onto the Inspector. It should print 10! Obviously, this setup can be used for more advanced features than this, but as long you really understand *how* it all worked, you should figure out everything else related to Resources.
  222. .. note::
  223. Resource scripts are similar to Unity's ScriptableObjects. The Inspector
  224. provides built-in support for custom resources. If desired though, users
  225. can even design their own Control-based tool scripts and combine them
  226. with an :ref:`EditorPlugin <class_EditorPlugin>` to create custom
  227. visualizations and editors for their data.
  228. Unreal Engine's DataTables and CurveTables are also easy to recreate with
  229. Resource scripts. DataTables are a String mapped to a custom struct, similar
  230. to a Dictionary mapping a String to a secondary custom Resource script.
  231. .. tabs::
  232. .. code-tab:: gdscript GDScript
  233. # bot_stats_table.gd
  234. extends Resource
  235. const BotStats = preload("bot_stats.gd")
  236. var data = {
  237. "GodotBot": BotStats.new(10), # Creates instance with 10 health.
  238. "DifferentBot": BotStats.new(20) # A different one with 20 health.
  239. }
  240. func _init():
  241. print(data)
  242. .. code-tab:: csharp
  243. using Godot;
  244. [GlobalClass]
  245. public partial class BotStatsTable : Resource
  246. {
  247. private Godot.Collections.Dictionary<string, BotStats> _stats = new Godot.Collections.Dictionary<string, BotStats>();
  248. public BotStatsTable()
  249. {
  250. _stats["GodotBot"] = new BotStats(10); // Creates instance with 10 health.
  251. _stats["DifferentBot"] = new BotStats(20); // A different one with 20 health.
  252. GD.Print(_stats);
  253. }
  254. }
  255. Instead of inlining the Dictionary values, one could also, alternatively:
  256. 1. Import a table of values from a spreadsheet and generate these key-value pairs.
  257. 2. Design a visualization within the editor and create a plugin that adds it
  258. to the Inspector when you open these types of Resources.
  259. CurveTables are the same thing, except mapped to an Array of float values
  260. or a :ref:`Curve <class_Curve>`/:ref:`Curve2D <class_Curve2D>` resource object.
  261. .. warning::
  262. Beware that resource files (\*.tres/\*.res) will store the path of the script
  263. they use in the file. When loaded, they will fetch and load this script as an
  264. extension of their type. This means that trying to assign a subclass, i.e. an
  265. inner class of a script (such as using the ``class`` keyword in GDScript) won't
  266. work. Godot will not serialize the custom properties on the script subclass properly.
  267. In the example below, Godot would load the ``Node`` script, see that it doesn't
  268. extend ``Resource``, and then determine that the script failed to load for the
  269. Resource object since the types are incompatible.
  270. .. tabs::
  271. .. code-tab:: gdscript GDScript
  272. extends Node
  273. class MyResource:
  274. extends Resource
  275. @export var value = 5
  276. func _ready():
  277. var my_res = MyResource.new()
  278. # This will NOT serialize the 'value' property.
  279. ResourceSaver.save(my_res, "res://my_res.tres")
  280. .. code-tab:: csharp
  281. using Godot;
  282. public partial class MyNode : Node
  283. {
  284. [GlobalClass]
  285. public partial class MyResource : Resource
  286. {
  287. [Export]
  288. public int Value { get; set; } = 5;
  289. }
  290. public override void _Ready()
  291. {
  292. var res = new MyResource();
  293. // This will NOT serialize the 'Value' property.
  294. ResourceSaver.Save(res, "res://MyRes.tres");
  295. }
  296. }