Calling a GDScript that is a field in a Resource doesn't work.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By timujin

Code:

// TestResource.gd

extends Resource
class_name TestResource
export(GDScript) var scr

// Poker.gd

extends GDScript

func poke():
	print("poked")
	return 1

Then, inside a scene, I put this script on a node:

extends Node

export var x:Resource

func _ready():
	print("before")
    print(x.scr.poke())
	print("after")

I create a resource of type TestResource, and I put Poker.gd into its ‘scr’ field. Then I put the created resource into the exported variable into the Node

This is the output:

before
Null
after

In other words. A Node references a Resource that references a GDscript that defines a function. But calling this function from Node does nothing and returns Null. Notably, Godot can tell that the function exists – if I call ‘print(x.scr.error())’, it will complain that there is no such function as ‘error’ in the script. It can see the function, but the function doesn’t work.

What’s going on here?

:bust_in_silhouette: Reply From: Zylann

poke() is what we usually call an “instance method”. All methods declared with just func are instance methods. It means they are callable on instances of the script, not the script itself.
This concept stems from Object Oriented programming. There are instance methods, and class methods. Instance methods work on instances of the class, and class methods work on the class itself (they are also called “static”).

Here, you did not create an instance of the script. src only references the script resource itself. So it won’t work, and I’m surprised Godot isn’t giving you runtime errors.

You may want to create an instance of the script, although I’m not sure how you can do that in the editor (also I have no clue what your intention is here). I’m also confused about what you are trying to achieve here. You made a custom resource type, which is a script already, and creating one will make an instance of it. Then you made it hold another script, for… what? Why can’t you put the data and functions you want in the resource script already?

Another way is to add the static keyword before your function, to indicate that it’s a class method. Although, in Godot, static methods cannot refer to variables of the class, also because variables are tied to instances.

Also, extends GDScript looks suspicious. All scripts are GDScripts already, but it’s not about inheritance. It’s very likely this isn’t doing what you want to do.