Resources & Loading
Resource is a refcounted data container that can be saved to disk (.tres text / .res binary) and shared.
26.1 What a Resource is
Resource is a refcounted data container that can be saved to disk (.tres text / .res binary) and shared. Textures, meshes, audio, materials, scenes (PackedScene), fonts, and themes are all resources. Loaded resources are cached: loading the same path twice returns the same instance.
26.2 Custom resources
Create instances via *FileSystem → New Resource → ItemData*, edit them in the Inspector, and save as sword.tres.
Resources are a great way to make data-driven games: enemy stats, weapon definitions, dialogue, level configs.
# res://data/item_data.gd
class_name ItemData
extends Resource
@export var id: StringName
@export var display_name := ""
@export_multiline var description := ""
@export var icon: Texture2D
@export var price := 0
@export var stackable := true
@export_range(1, 999) var max_stack := 99@export var item: ItemData # assign sword.tres in the Inspector
func _ready() -> void:
$Icon.texture = item.icon
$Name.text = item.display_name26.3 Shared vs unique
Because resources are shared, modifying item.price at runtime changes it for every user of that resource. Use:
or enable *Local to Scene* (resource_local_to_scene = true) so each scene instance gets its own copy.
var my_stats: CharacterStats = base_stats.duplicate() # independent copy (duplicate(true) for sub-resources)26.4 preload vs load
| | preload | load | |-|-----------|--------| | When | When the script loads | When the line executes | | Path | Constant string only | Any expression | | Use | Small, always-needed assets | Optional or dynamic assets |
const Bullet := preload("res://scenes/bullet.tscn") # loaded at script compile/load time; path must be constant
var level := load("res://levels/level_%d.tscn" % n) # loaded at runtime (blocking)
var tex := load("res://missing.png") as Texture2D # null + error if missing
if ResourceLoader.exists("res://levels/level_9.tscn"):
pass26.5 Background (threaded) loading
const LEVEL := "res://levels/big_level.tscn"
@onready var bar: ProgressBar = $ProgressBar
func _ready() -> void:
ResourceLoader.load_threaded_request(LEVEL)
func _process(_delta: float) -> void:
var progress := []
var status := ResourceLoader.load_threaded_get_status(LEVEL, progress)
match status:
ResourceLoader.THREAD_LOAD_IN_PROGRESS:
bar.value = progress[0] * 100.0
ResourceLoader.THREAD_LOAD_LOADED:
var scene: PackedScene = ResourceLoader.load_threaded_get(LEVEL)
get_tree().change_scene_to_packed(scene)
ResourceLoader.THREAD_LOAD_FAILED, ResourceLoader.THREAD_LOAD_INVALID_RESOURCE:
push_error("Failed to load " + LEVEL)
set_process(false)26.6 Saving resources
Security: .tres/.res files can embed scripts. Loading resource files that players can edit or download can execute arbitrary code. For save files that may be shared, prefer JSON/ConfigFile or store_var without objects.
var err := ResourceSaver.save(my_resource, "user://inventory.tres")
if err != OK:
push_error("Save failed: %s" % error_string(err))