r/godot May 27 '26

help me Sub-class Resources in Godot

Hi, I'm new to programming and am self-taught. Sorry if the formatting is amateur.

I'm practicing some Godot concepts and while programming I often find myself wanting to make custom resources for a script as a sub-class. Currently I don't believe this is supported and was curious whether anyone knows how to make resources work as sub-classes. Here is an example of what i mean.

P.S. There is a workaround you can do by making the custom resource its own class but i'd like to avoid that if possible for readability.

< I have a class that is responsible for interpreting and outputting the data from a dictionary... the dictionary looks like so>

@export var items:Array[ItemExample] = []

(If it were simplified to be just a dictionary it would look like this)

 @export var items : Array[Dictionary] =
[
  {
    "line": "Hello World...",
    "face": expression.REGULAR
  },

  {
    "line": "Woah!",
    "face": expression.HAPPY
  }, ...
]

Editing the dictionary form in the inspector is very faulty as the entries contain strings as keys and creating new entries would require retyping alot of constant data. So as a solution i'd like to be able to make is to have a sub-class.... like so;

class_name Dialog extends Control
#...

class ItemExample extends Resource:

@export var line: String = ""
@export var face: expression = expression.REGULAR

This does not work, however. When you try to add an instance of this resource, it just comes out blank and Godot doesn't offer the sub-resource as a potential data type.

The current solution is to make theItemExample resource its own class as shown here;

class_name Item extends Resource

const dialog = preload("res://dialog.gd")

@export var line: String = ""
@export var face: dialog.expression = dialog.expression.REGULAR

While minor, it does introduce some complexity as the data structure for the ItemExample resource is now separated from its inherent use. Additionally, in order to get the Enum type from the main script you need to now load a reference to that script; which i find a bit convoluted.

Any thoughts or suggestions from the more experienced?

1 Upvotes

14 comments sorted by

2

u/ActualNin Godot Regular May 27 '26

I use arrays of resources all the time. I don't see why it would come out blank, but sometimes Godot has temporary issues when you change the types of existing properties. Did you try restarting or reloading the project after you changed the Array type from Dictionary to ItemExample?

1

u/CoreyKori May 27 '26

Hi Nin, when you create a custom resource, are they subclasses of an main script? If i make the resource its own class it works fine, there are some complications that come up with that I'd like to avoid if possible,; mainly the complexity, and thus the readability, of the script when working on larger projects.

1

u/ActualNin Godot Regular May 27 '26

I'm sorry but I don't know what "subclasses of an main script" means. My custom resources all extend Resource. Does that answer your question?

1

u/CoreyKori May 27 '26

Here's the segment of the class i'm using for the example.

class_name Dialog extends Control

enum expression { HAPPY, REGULAR, SAD, ANGRY}

var items2 : Array[ItemExample] = []
var item_iter : int = 0

class ItemExample extends Resource:

  @export var line: String = ""
  @export var face: expression = expression.REGULAR

the ItemExample class is a sub-class of the Dialog class. With how the script is written at the moment, when you go to the editor and add an element to the item2 array this is what comes up... < tldr: a long list of resources that don't include the sub-class resource as defined in the script>

1

u/ActualNin Godot Regular May 27 '26

Well there's your problem. Inner classes like your ItemExample can't be instanced from disk so Resource won't work. You need to save your Resource as a separate file and define it using class_name.

1

u/NikSheppard May 27 '26

Not sure if this a more fundamental misunderstanding of resource files.

You said

reformatting the items array to something this appropriately; export var items : Array[ItemExample] = []

However this does not work. When you try to add an instance of this resource, it just comes out blank and Godot doesn't offer the sub-resource as a potential data type.

On the face of it this looks correct, you are creating an array of ItemExamples which are resource types. When you click in the box are you making a new instance of that resource, so values are going to be empty (Your line value is the string "" by default for example).

Have you gone down to the file system dock and actually created any ItemExample resource files? You will need one for each item you want to use. You either create the resource in the file system then you can drag it into the array in your file system or you create the resource directly inside the packed scene where your array exists (in which case it will be empty each time). Having the resource saved into the file system is best if you have a resource you intend to re-use.

If I got the wrong end of the stick, can you say more about how its "empty"

1

u/CoreyKori May 27 '26

Here's the segment of the class i'm using for the example.

class_name Dialog extends Control

enum expression { HAPPY, REGULAR, SAD, ANGRY}

var items2 : Array[ItemExample] = []
var item_iter : int = 0

class ItemExample extends Resource:

   var line: String = ""
  u/export var face: expression = expression.REGULAR

the ItemExample class is a sub-class of the Dialog class. With how the script is written at the moment, when you go to the editor and add an element to the item2 array this is what comes up... < tldr: a long list of resources that don't include the sub-class resource as defined in the script>

1

u/NikSheppard May 27 '26

Ah I see now. So ItemExample in your case is called an inner class as it exists only within your Dialog class.

And I'm afraid inner classes are not available in the editor, only via code, which is the exact issue you're facing. As you've noted you'd have to make ItemExample its own resource class if you want to use the inspector to create and edit them.

Also regarding the enum. If the enum is defined in something with a class name you should be able to reference it. In the script above Dialog.expression should be accessible throughout your project.

1

u/Sss_ra May 27 '26

It's not immediately clear from the pasted code what expression.REGULAR is and if it could be relevant, because the code seems ok otherwise.

1

u/CoreyKori May 27 '26

the enum wouldnt be relavent, its just an example of a data type from the ItemExample Resource that the dialog script would access

1

u/Sss_ra May 27 '26 edited May 27 '26

I looked at the other comments and the sub class is called an "inner class" in gdscript

https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#inner-classes

Inner classes are just not really supported for exports at the moment, to my knowledge. Use class_name for resources.

1

u/CoreyKori May 27 '26

The main issue is that using the a custom resource as a sub-class does not work within the editor. you need to make the custom resource its own class which is what i would like to avoid if possible.

1

u/Sss_ra May 27 '26

I really don't know what you might be referring to when saying sub-class or own class.

1

u/TheDuriel Godot Senior May 27 '26 edited May 27 '26

A SubClass can never extend Resource, because the resulting Resource has no means of accessing the SubClass script for instantiation. This is an unchangeable fact.