Before I start, I wanted to note that I’ve spent a few hours googling around for forum posts and reading docs. I’ve worked as a pro Unity dev before, but I’m trying to do things the Godot way rather than fight the engine.
I’m working on setting up domain object loading and saving on my (data heavy) project. As best as I can tell, Godot’s intended way to represent this kind of arbitrary (de)serializable and inspectable data is with resources, but I’m having some difficulty understanding how Resource importers should be set up for everything. I’ve ultimately trying to get objects deserialized from static row data loaded from a spreadsheet.
So far, I’m using a custom ResourceFormatImporter to bring in TSV data exported from spreadsheets as a custom TsvTable resource. As I understand it, this should let me import a TSV file in the editor to save as a resource file in Godot’s bespoke file format. I’m stuck on how to set up the next step, which is to load the actual domain objects during game runtime. Ideally, I’d like to write in some node’s script:
this.stats = GD.Load<EnemyStats>(“enemy_smol_goblin“)
after registering some method or class that can do the TsvTable→EnemyStats conversion. I don’t see how to do this - ResourceFormatLoader is about directly doing file IO, and ResourceLoader is the central singleton that orchestrates loading. EditorImportPlugin seems to also be able to handle some of this, but it runs in editor time rather than build or runtime.
If anyone could set me in the right direction, I’d be very thankful.
I think you already got it.
My Resource:
using Godot;
[GlobalClass]
public partial class UnitDefinition : Resource
{
[ExportGroup("Infos")]
[Export] public string Name { get; set; } = "Unnamed Unit";
[Export] public string Description { get; set; }
[Export] public Texture2D Icon { get; set; }
[ExportGroup("Stats")]
[Export] public int BaseHealth { get; set; } = 100;
[Export] public float BaseSpeed { get; set; } = 4f;
}
3 ways to load your resource:
Assign them via exported property, or load them via GD.Load using its path or uid:
using Godot;
public partial class Unit : Node3D
{
[Export] public UnitDefinition definition;
public int Health;
public float Speed;
public override void _Ready()
{
//definition = GD.Load<UnitDefinition>("uid://dpddfjjbvwvqh");
definition = GD.Load<UnitDefinition>("res://source/gameplay/unit/Dummy.tres");
GD.Print(definition.BaseHealth);
GD.Print(definition.BaseSpeed);
Health = definition.BaseHealth;
Speed = definition.BaseSpeed;
}
public override void _Process(double delta)
{
}
}
Thanks for the reply, but I think you’re describing the out-of-the-box behavior for deserializing resources. I’m looking for the hooks to provide custom deserialization behavior that depends on another resource. Basically, I’ve got a function that looks like:
public static Background Load(string key)
{
var line = ResourceLoader.Load($“res://Data/Backgrounds.tres”).Data[key];
return new Background(){
Name = line.OptionallyGet(“Name”).OrThrow(),
//...
}
}
that I’d like GD to run automagically during resource loading to instantiate the various domain objects that live in the TSV table. That wouldn’t be covered by a simple load because whatever “key” is up there wouldn’t be a file or UUID, it would need to call this extra behavior to deserialize things.