How to save/load custom resource arrays?

Godot Version

4.2.1

Question

How do I save/load custom resource classes that are nested into arrays? My resource saves to a file, but loading it gives me errors.

Here’s a example (3 short source files) that fails:
=== File 1/3 o_event.gd ===

class_name OEvent extends Resource

@export var title : String = ""

func _init(string : String) -> void:
	title = string

=== o_event.gd END ===

=== File 2/3 o_events.gd ===

class_name OEvents extends Resource

@export var events : Array[OEvent] = []

func append_event(string : String) -> OEvent:
	var o_event : OEvent = OEvent.new(string)
	events.append(o_event)
	return o_event

=== o_events.gd END ===

=== File 3/3 main.gd ===

extends Control

var o_events : OEvents = null

func _ready():
	o_events = OEvents.new()
	o_events.append_event("Test")
	
func _on_save_button_pressed():
	ResourceSaver.save(o_events, "res://demo_resource.tres")

func _on_load_button_pressed():
	var loaded_resource : OEvents = ResourceLoader.load("res://demo_resource.tres")
	print(loaded_resource.events)

=== main.gd END ===

At the ResourceLoader.load() call in _on_load_button_pressed(), I get the following errors:

E 0:00:04:0103   Main.gd:13 @ _on_load_button_pressed(): Error constructing a GDScriptInstance.
  <C++ Error>    Method/function failed. Returning: nullptr
  <C++ Source>   modules/gdscript/gdscript.cpp:188 @ _create_instance()
  <Stack Trace>  Main.gd:13 @ _on_load_button_pressed()

E 0:00:04:0103   Main.gd:13 @ _on_load_button_pressed(): Attempted to assign an object into a TypedArray, that does not inherit from 'GDScript'.
  <C++ Error>    Condition "other_script.is_null()" is true. Returning: false
  <C++ Source>   core/variant/container_type_validate.h:139 @ validate_object()
  <Stack Trace>  Main.gd:13 @ _on_load_button_pressed()

E 0:00:04:0103   Main.gd:13 @ _on_load_button_pressed(): unsupported format character
  <C++ Error>    Condition "error" is true. Returning: String()
  <C++ Source>   ./core/variant/variant.h:834 @ vformat()
  <Stack Trace>  Main.gd:13 @ _on_load_button_pressed()

How should I rewrite the code so it loads the resource without issues?

Godot expects resources to have a parameterless init method. See here.

You could try this:

class_name OEvent extends Resource

@export var title : String = ""

class_name OEvents extends Resource

@export var events : Array[OEvent] = []

func append_event(string : String) -> OEvent:    
    var o_event: OEvent = OEvent.new()
    o_event.title = string
    events.append(o_event)
    return o_event

hope it helps!

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