Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Zdroje

Uzly a zdroje

Až do tohoto tutoriálu jsme se v Godotu zaměřovali na třídu Node, protože právě ta se používá k programování chování a většina funkcí enginu závisí právě na ní. Existuje však ještě jeden datový typ, který je stejně důležitý: Resource.

Uzly poskytují funkce: kreslí sprity, 3D modely, simulují fyziku, uspořádávají uživatelská rozhraní atd. Zdroje jsou kontejnery dat. Samy o sobě nic nedělají: místo toho jsou data v nich obsažená používána uzly.

Anything Godot saves or loads from disk is a resource. Be it a scene (a .tscn or an .scn file), an image, a script... Here are some Resource examples:

Když engine načítá zdroj z disku, načítá jej pouze jednou. Pokud je kopie tohoto zdroje již v paměti, pokus o jeho opětovné načtení pokaždé vrátí stejnou kopii. Jelikož prostředky obsahují pouze data, není třeba je duplikovat.

Každý objekt, ať už je to uzel nebo zdroj, může exportovat vlastnosti. Existuje mnoho typů vlastností, například String, integer, Vector2 atd., a každý z těchto typů se může stát zdrojem. To znamená, že jak uzly, tak zdroje mohou obsahovat zdroje jako vlastnosti:

../../_images/nodes_resources.webp

Externí vs. vestavěný

Zdroje lze ukládat dvěma způsoby. Mohou to být:

  1. Externí ke scéně, uložené na disku jako jednotlivé soubory.

  2. Vestavěné, uložené uvnitř souboru .tscn nebo souboru .scn, ke kterému jsou připojeny.

To be more specific, here's a Texture2D in a Sprite2D node:

../../_images/spriteprop.webp

Clicking the resource preview allows us to view the resource's properties.

../../_images/resourcerobi.webp

Vlastnost path nám říká, odkud prostředek pochází. V tomto případě pochází z obrázku PNG s názvem robi.png. Pokud zdroj pochází z takového souboru, jedná se o externí zdroj. Pokud cestu vymažete nebo je tato cesta prázdná, stane se vestavěným zdrojem.

K přepnutí mezi vestavěnými a externími zdroji dojde při ukládání scény. Pokud ve výše uvedeném příkladu vymažete cestu "res://robi.png" a uložíte, Godot uloží obrázek uvnitř souboru scény .tscn.

Poznámka

I když vestavěný zdroj uložíte, při vícenásobném instancování scény načte engine pouze jeho jednu kopii.

Načítání zdrojů z kódu

Existují dva způsoby načítání zdrojů z kódu. Za prvé můžete kdykoli použít funkci load():

func _ready():
    # Godot loads the Resource when it reads this very line.
    var imported_resource = load("res://robi.png")
    $sprite.texture = imported_resource

You can also preload resources. Unlike load, this function will read the file from disk and load it at compile-time. As a result, you cannot call preload with a variable path: you need to use a constant string.

func _ready():
    # Godot loads the resource at compile-time
    var imported_resource = preload("res://robi.png")
    get_node("sprite").texture = imported_resource

Načítání scén

Scenes are also resources, but there is a catch. Scenes saved to disk are resources of type PackedScene. The scene is packed inside a Resource.

To get an instance of the scene, you have to use the PackedScene.instantiate() method.

func _on_shoot():
        var bullet = preload("res://bullet.tscn").instantiate()
        add_child(bullet)

Tato metoda vytvoří uzly v hierarchii scény, nakonfiguruje je a vrátí kořenový uzel scény. Ten pak můžete přidat jako potomka jakéhokoli jiného uzlu.

The approach has several advantages. As the PackedScene.instantiate() function is fast, you can create new enemies, bullets, effects, etc. without having to load them again from disk each time. Remember that, as always, images, meshes, etc. are all shared between the scene instances.

Uvolnění zdrojů

When a Resource is no longer in use, it will automatically free itself. Since, in most cases, Resources are contained in Nodes, when you free a node, the engine frees all the resources it owns as well if no other node uses them.

Vytváření vlastních zdrojů

Stejně jako jiné objekty v Godotu mohou uživatelé zdroje také skriptovat. Skripty zdrojů dědí schopnost volně překládat mezi vlastnostmi objektu a serializovaným textem nebo binárními daty (*.tres, *.res). Od typu Reference také dědí správu paměti počítáním referencí.

This comes with many distinct advantages over alternative data structures, such as JSON, CSV, or custom TXT files. Users can only import these assets as a Dictionary (JSON) or as a FileAccess to parse. What sets Resources apart is their inheritance of Object, RefCounted, and Resource features:

  • Mohou definovat konstanty, takže konstanty z jiných datových polí nebo objektů nejsou potřeba.

  • Mohou definovat metody, včetně metod setter/getter pro vlastnosti. To umožňuje abstrakci a zapouzdření základních dat. Pokud je třeba změnit strukturu skriptu Resource, nemusí se měnit ani hra, která Resource používá.

  • Mohou definovat signály, takže Zdroje mohou spouštět reakce na změny ve spravovaných datech.

  • Mají definované vlastnosti, takže uživatelé stoprocentně vědí, že jejich data budou existovat.

  • Automatická serializace a deserializace zdrojů je integrovanou funkcí Godot Engine. Uživatelé nemusí implementovat vlastní logiku pro import/export dat souboru zdrojů.

  • Zdroje mohou dokonce rekurzivně serializovat dílčí zdroje, což znamená, že uživatelé mohou navrhovat ještě sofistikovanější datové struktury.

  • Uživatelé mohou ukládat zdroje jako textové soubory vhodné pro správu verzí (*.tres). Při exportu hry Godot serializuje soubory zdrojů jako binární soubory (*.res) pro zvýšení rychlosti a komprese.

  • Inspector v Godot Engine nativně podporuje vykreslování a úpravu souborů zdrojů. Uživatelé tak často nemusí implementovat vlastní logiku pro vizualizaci nebo úpravy dat. Za tímto účelem dvakrát klikněte na soubor prostředku v doku FileSystem nebo klikněte na ikonu složky v Inspectoru a otevřete soubor v dialogovém okně.

  • Mohou rozšiřovat jiné typy zdrojů než jen základní Zdroj.

Godot usnadňuje vytváření vlastních zdrojů v Inspektoru.

  1. Vytvořte v Inspektoru obyčejný objekt Zdroj. Může to být i typ od Zdroj odvozený, pokud váš skript tento typ rozšiřuje.

  2. Nastavte vlastnost script v Inspektoru na váš skript.

V Inspektoru se nyní zobrazí přidané vlastnosti skriptu zdroje. Pokud tyto hodnoty upravíte a zdroj uložíte, inspektor serializuje i tyto přidané vlastnosti! Chcete-li zdroj uložit z Inspektora, klikněte na nabídku nástrojů Inspektora (vpravo nahoře) a vyberte možnost "Uložit" nebo "Uložit jako...".

Pokud jazyk skriptu podporuje třídy skriptů, pak se tento proces zjednodušuje. Samotné definování názvu skriptu jej přidá do dialogu Inspektoru pro vytvoření. Tím se váš skript automaticky přidá k vytvořenému objektu Resource.

Let's see some examples. Create a Resource and name it bot_stats. It should appear in your file tab with the full name bot_stats.tres. Without a script, it's useless, so let's add some data and logic! Attach a script to it named bot_stats.gd (or just create a new script, and then drag it to it).

extends Resource

@export var health: int
@export var sub_resource: Resource
@export var strings: PackedStringArray

# Make sure that every parameter has a default value.
# Otherwise, there will be problems with creating and editing
# your resource via the inspector.
func _init(p_health = 0, p_sub_resource = null, p_strings = []):
    health = p_health
    sub_resource = p_sub_resource
    strings = p_strings

Now, create a CharacterBody3D, name it Bot, and add the following script to it:

extends CharacterBody3D

@export var stats: Resource

func _ready():
    # Uses an implicit, duck-typed interface for any 'health'-compatible resources.
    if stats:
        stats.health = 10
        print(stats.health)
        # Prints "10"

Now, select the 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.

Poznámka

Skripty prostředků jsou podobné skriptovatelným objektům Unity. Inspector poskytuje vestavěnou podporu pro vlastní zdroje. V případě potřeby však mohou uživatelé navrhnout i vlastní skripty nástrojů založené na nástroji Control a zkombinovat je s EditorPlugin a vytvořit tak vlastní vizualizace a editory pro svá data.

Unreal Engine's DataTables and CurveTables are also easy to recreate with Resource scripts. DataTables are a String mapped to a custom struct, similar to a Dictionary mapping a String to a secondary custom Resource script.

# bot_stats_table.gd
extends Resource

const BotStats = preload("bot_stats.gd")

var data = {
    "GodotBot": BotStats.new(10), # Creates instance with 10 health.
    "DifferentBot": BotStats.new(20) # A different one with 20 health.
}

func _init():
    print(data)

Instead of inlining the Dictionary values, one could also, alternatively:

  1. Import a table of values from a spreadsheet and generate these key-value pairs.

  2. Design a visualization within the editor and create a plugin that adds it to the Inspector when you open these types of Resources.

Tabulky křivek jsou totéž, jen jsou mapovány na pole hodnot float nebo na objekt zdroje Curve/Curve2D.

Varování

Pozor na to, že soubory zdrojů (*.tres/*.res) ukládají cestu ke skriptu, který používají, do souboru. Při načítání se tento skript načte jako rozšíření jejich typu. To znamená, že pokus o přiřazení podtřídy, tj. vnitřní třídy skriptu (např. pomocí klíčového slova class v GDScript) nebude fungovat. Godot nebude správně serializovat vlastní vlastnosti podtřídy skriptu.

V níže uvedeném příkladu by Godot načetl skript Node, zjistil by, že nerozšiřuje Resource, a poté by určil, že se skript nepodařilo načíst pro objekt Resource, protože typy jsou nekompatibilní.

extends Node

class MyResource:
    extends Resource
    @export var value = 5

func _ready():
    var my_res = MyResource.new()

    # This will NOT serialize the 'value' property.
    ResourceSaver.save(my_res, "res://my_res.tres")