Saving Nested Custom Resources

Godot Version

v4.5-stable

Question

I’m trying to implement save/load functionality using a custom nested Resource stored in a .tres file, but I’m running into an issue where my typed array doesn’t seem to persist correctly.

Here’s a simplified example:

class_name MyResource
extends Resource

@export var amount: int

func _init(_amount: int) -> void:
    self.amount = _amount
class_name MyResourceStore
extends Resource

@export var my_array: Array[MyResource]

func _init() -> void:
    my_array = [MyResource.new(5)]

And here’s how I’m saving/loading it:

extends Node2D

const PATH := "user://my_resource_store.tres"

func _ready() -> void:
    var original_store: MyResourceStore = MyResourceStore.new()
    ResourceSaver.save(original, PATH)
    var loaded_store: MyResourceStore = ResourceLoader.load(PATH)

    print(loaded_store.my_array[0].amount) # Expected: 5

The issue is that loaded_store.my_array is empty, but I expected it to have a MyResource with amount 5.

Changing the typed array Array[MyResource] to a untyped Array makes loaded_store.my_array have the correct size of 1, but it contains a dummy resource without a script, so is not recognized as a MyResource and doesn’t have an amount field.

Why does the typed Array[MyResource] not get saved/loaded properly? Is there an extra step needed to make ResourceLoader load custom resources?

1 Like

For reference, this is what the my_resource_store.tres file looks like on disk. It seems like it saved the correct information. But it doesn’t get loaded correctly.

[gd_resource type="Resource" script_class="MyResourceStore" load_steps=4 format=3]

[ext_resource type="Script" path="res://manual_testing/my_resource.gd" id="1_pn5nv"]
[ext_resource type="Script" path="res://manual_testing/my_resource_store.gd" id="2_ccoyq"]

[sub_resource type="Resource" id="Resource_mc5ln"]
script = ExtResource("1_pn5nv")
amount = 5

[resource]
script = ExtResource("2_ccoyq")
my_array = Array[ExtResource("1_pn5nv")]([SubResource("Resource_mc5ln")])
1 Like

Resources can’t have required parameters in their Object._init() function as the engine will fail to load them back. You can give it a default parameter instead.

From the documentation:

Note: If _init() is defined with required parameters, the Object with script may only be created directly. If any other means (such as PackedScene.instantiate() or Node.duplicate()) are used, the script’s initialization will fail.

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.