How can I get the Script type of a node?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By chanon
:warning: Old Version Published before Godot 3 was released.

I want to be able to detect if a given node has a given script type attached.

Suppose I have a 2D Sprite node named “mySprite” with a script file named “MySprite.gd”

In the parent of mySprite’s script I do

const MySprite = preload("/path/to/MySprite.gd")

var spr = get_node("mySprite")
print( spr extends MySprite )

I thought this would be True but this results in False.

If I try printing spr:

print( str(spr) )

This results in [Sprite:588] instead of [MySprite:…]

EDIT:

I found out about get_script() however, I still can’t make it work:

print(spr.get_script() == MySprite)
print(spr.get_script() extends MySprite)
print(spr.get_script().instance_has(MySprite) )
print(MySprite.instance_has(spr))
print(MySprite.instance_has(spr.get_script()))

All of the above print “False”

However if I do:

print(MySprite.get_source_code())
print(spr.get_script().get_source_code())

The output source code is identical.

EDIT:

I found out the problem. I tried doing

print(MySprite.get_path())
print(spr.get_script().get_path())

Turns out the result is:

res:///path/to/MySprite.gd
res://path/to/MySprite.gd

The paths are different when using absolute paths and relative paths! (The mySprite node uses a relative path). This causes the script object instances to be different. If I change it to both use relative paths then the script object becomes the same instance. I believe this is a bug which could be causing unnecessary loading of resources multiple times.

Note: bug filed here:

:bust_in_silhouette: Reply From: chanon

(Answering my own question)

The correct answer is:

const MySprite = preload("res://path/to/MySprite.gd")

var spr = get_node("mySprite")
print( spr extends MySprite)

The above will print True. The important thing is to use “res://path/to/MySprite.gd” as using “/path/to/MySprite.gd” results in the path being resolved to “res:///path/to/MySprite.gd”.

I don’t know if it is a bug or not, but it seems best practice is to use “res://path/to/thing” style paths for everything in GDScript.

This is because it looks like others have also had problems with non res:// style paths:

Also there are not so many problems with relative paths, I’m using them all the time. One of the issues you had linked is more related to the fact that relative paths in Godot should not be started with “/” character.

kubecz3k | 2016-04-11 14:48

Yes, I guess relative paths most of the time should be ok (except for issue 4026 above). In any case that should be fixed eventually.

chanon | 2016-04-11 14:54

Note: In Godot 3.0 and later, the extends keyword for the purposes of type comparisons has been replaced with is:

if get_node("MyNode") is KinematicBody2D:
    print("MyNode inherits from KinematicBody2D.")

Calinou | 2021-07-02 15:04

:bust_in_silhouette: Reply From: kubecz3k

For comparisons I would use extends keyword instead, in that case you don’t even need to use get_script() at all, just:

const MySpriteClass = preload("res://path/to/MySprite.gd")
var sprNode = get_node("mySprite")

(...)

var nodeExtendingSpriteClass = sprNode extends MySpriteClass; #true/false
print("spr node is an instance of MySpriteClass: ", str(nodeExtendingSpriteClass))

If you really need to get exactly “Class” of a scipt then I don’t know if there is any direct method to do this… But you still can get path to the script file with:
var scriptFilePath = node.get_script().get_path()

So if a name of a file is a name of a class then it would be:
var scriptName = node.get_script().get_path().get_file()

Yes, actually I just figured that out while fixing my code and came to update my answer.
I had the right idea right at the beginning … it was just due to the absolute path resolution bug.

chanon | 2016-04-11 14:49

If you think this answer is better you should choose it, this way any person that will come in the future will be able to benefit.

kubecz3k | 2016-04-11 15:01

Sorry, I edited my answer already … I’ll choose yours anyway :slight_smile:

chanon | 2016-04-11 15:09

Note: In Godot 3.0 and later, the extends keyword for the purposes of type comparisons has been replaced with is:

if get_node("MyNode") is KinematicBody2D:
    print("MyNode inherits from KinematicBody2D.")

Calinou | 2021-07-02 15:04