+5 votes

I have a GDScript class/script, for example this one:

class LevelAchievements:
var best_time = -1.0
var collected_orbs = 0
var death_count = -1
var completed_count = 0

var data = LevelAchievements.new()

In order to write it inside a savegame file, I want to iterate over its members rather than copy/paste everyting on save and load. Usually, this can be done through a form of reflection, but how is it possible to do that in GDScript?

Even better, is there a whay to query which members have export, and if so what is their type etc?

in Engine by (27,831 points)

Not that I know of. There's get_method_list() for functions but that's all I can see. I use pretty much the save game method described in the manual.

I see there is get_property_list(), accordint to the doc it should return this:

Return the list of properties as an array of dictionaries, dictionaries contain: name:String, type:int (see TYPE_* enum in globals) and optionally: hint:int (see PROPERTY_HINT_* in globals), hint_string:String, usage:int (see PROPERTY_USAGE_* in globals).

So I tried:

class Foo:
    var one = 1
    var two = "two"
    var three

func _ready():
    var obj = Foo.new()
    var list = obj.get_property_list()
    for d in list:
        print("> " + d["name"])

But the result is completely off Oo

> Reference

I tried this instead:

var list = Foo.get_property_list()
for d in list:
    print("> " + d["name"])

More weirdness :o

> Reference
> Resource
> resource/path
> resource/name
> Script
> GDScript
> script/source

Either its a bug, or the function is badly named...

Yeah i tried that too. I don't think it's properties as we know it.

A workaround would be to use var data = inst2dict(obj) and var obj = dict2inst(data), but it gets all properties, including @path and @subpath to indentify the class.

1 Answer

+1 vote

Your list is a dictionary array, iterate it this way:

var properties = node.get_property_list()

for i in range(properties.size()):
    print(properties[i].name + ", type: " + str(properties[i].type))

and to obtain the value by name use get:

var value = node.get("property_name")
by (992 points)

It doesn't works on classes:

class Test:
    var one = 1
    var two = "hahah"
    var three = []

Only prints:

Reference, type: 0

Adding export to the vars doesn't change anything.

Definitly a bug, it works with nodes, as a workaround you can extend your classes from Node until it's fixed:

class Test extends Node:

Even that won't work for my use case, unfortunately...

In Godot 3.2 stable the answer given by davidoc works correctly.

The following code


class LevelAchievements:
var besttime = -1.0
var collected
orbs = 0
var deathcount = -1
var completed
count = 0 func saveTest(file : String) -> void: pass

func _ready():  
    var data = LevelAchievements.new()
    data.best_time = 55.5
    data.collected_orbs = 100
    data.death_count = 20
    data.completed_count = 22
    var properties = data.get_property_list()
    for i in range(properties.size()):
        print(properties[i].name + ", type: " + str(properties[i].type) + " = " + str(data.get(properties[i].name)))
    var properties2 = data.get_method_list()
    print(properties2)

Gives the following output
Reference, type: 0 = Null
Script, type: 0 = Null
script, type: 17 = [GDScript:1184]
Script Variables, type: 0 = Null
besttime, type: 0 = 55.5
collected
orbs, type: 0 = 100
deathcount, type: 0 = 20
completed
count, type: 0 = 22
....Methods information with method name, input arguments, return type etc.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.