Let's say I have an object and I'm given a class name in string
How do I check if the object is of that class?
extends Node2D
func _ready():
var given_class_name="KinematicBody2D"
if($Obj is given_class_name):
...
You can use get_class()
to find the class of an Object
, ignoring Script
s. Which in this case should be sufficient:
var given_class_name="KinematicBody2D"
prints($Obj.get_class() == given_class_name)
But that is not every case, is it? Perhaps you want to check a base class, then this does not work:
var given_class_name="PhysicsBody2D"
prints($Obj.get_class() == given_class_name)
Instead we can use is_class
:
var given_class_name="PhysicsBody2D"
prints($Obj.is_class(given_class_name))
Or we can ask ClassDB
:
var given_class_name="PhysicsBody2D"
var obj_class := $Obj.get_class()
prints(
obj_class == given_class_name
or ClassDB.is_parent_class(given_class_name, obj_class)
)
But what about Script
classes?
Perhaps you remember that we can find the class name of a script by looking at _global_script_classes
, something like this:
var obj_class_name := $Obj.get_class()
var script:Script = $Obj.get_script()
if script != null:
obj_class_name = script.resource_path
for x in ProjectSettings.get_setting("_global_script_classes"):
if str(x["path"]) == script.resource_path:
script_class_name = str(x["class"])
The above code will set obj_class_name
to either:
$Obj
, if it has any.$Obj
, if it has any.$Obj
.However, since we want to check if it is of a given type that is not sufficient. Since we also need to check Script
inheritance. As it turn out it is more convenient to figure out what kind of class is the name we are given and work from there:
func is_instance_of(obj:Object, given_class_name:String) -> bool:
if ClassDB.class_exists(given_class_name):
# We have a build in class
return obj.is_class(given_class_name)
else:
# We don't have a build in class
# It must be a Script class
# Try to find the Script
var class_script:Script
for x in ProjectSettings.get_setting("_global_script_classes"):
if str(x["class"]) == obj_class_name:
class_script = load(str(x["path"]))
break
if class_script == null:
# Unknown class
return false
# Get the script of the object and try to match it
var check_script := obj.get_script()
while check_script != null:
if check_script == class_script:
return true
check_script = check_script.get_base_script()
# Match not found
return false
We are almost there. As you know, in GDScript you can extend using a script path (see Classes). So we might consider resource paths of script valid class names... We can support that too:
func is_instance_of(obj:Object, given_class_name:String) -> bool:
if ClassDB.class_exists(given_class_name):
# We have a build in class
return obj.is_class(given_class_name)
else:
# We don't have a build in class
# It must be a script class
var class_script:Script
# Assume it is a script path and try to load it
if ResourceLoader.exists(given_class_name):
class_script = load(given_class_name) as Script
if class_script == null:
# Assume it is a class name and try to find it
for x in ProjectSettings.get_setting("_global_script_classes"):
if str(x["class"]) == obj_class_name:
class_script = load(str(x["path"]))
break
if class_script == null:
# Unknown class
return false
# Get the script of the object and try to match it
var check_script := obj.get_script()
while check_script != null:
if check_script == class_script:
return true
check_script = check_script.get_base_script()
# Match not found
return false
You could go the extra mile and support a Variant instead of an Object
. Then you can check its type with typeof
... If it is TYPE_OBJECT
then you proceed to check for a class. If it isn't, you would need a giant switch to check the names of build it types (similar to the one here, but with the type names).
For anybody trying to do this in GODOT 4: ProjectSettings.get_setting("_global_script_classes")
does not work anymore. Instead use ProjectSettings.get_global_class_list()
.