Hello

I'm making a high score system.

Godot did not support global variables, so I also learned singletons.

I have not yet created a high score system with the godot engine.

So I looked up several posts on the Internet.

It seemed like a way to create a file, save it, and load it from that file. (https://godotengine.org/qa/31066/high-score-on-android)

But, as you can see from the screenshot, there is an error.

Even though I followed the code in the material almost as it is.

And I do not know when to call high scores.

auto load seemed to keep the values even if the scene was replaced or restarted

Once in the auto load script, I was given a screenshot to get the high score information

If the high score information changes, it may be reflected in real time.

Also, if you did not create a file in that path, does the godot engine create the file yourself?

The reason you are getting a unexpected token error is because the code you have for opening and loading data from a file needs to be in a function, not globally defined. You can put it in something like _ready or make your own function and then call it when you need (I would suggest going this, as it makes it easier to refactor)

Something like this should work:

func load_highscores():
	var f = File.new()
	f.open(easy_high_path, File.READ)
	easy_high_score = f.get_var()
	f.close()
	f.open(hard_high_path, File.READ)
	hard_high_score = f.get_var()
	f.close()

That should fix the issue.

@MungMoong said: And I do not know when to call high scores.

For a infinite runner project I made I just saved scores before Godot closes, and load scores when Godot is first started. This seemed to work well enough most of the time.

Another option is to save high scores when a level is completed. That way you can always have the most up to date scores stored on file, and so long as you are not writing a ton of data, it shouldn't be too slow and cause any noticeable lag.

Ultimately it really depends on how your game is setup and how you want to set it up. There are lots of way to go about it, so I'd just find one that works for you and stick to it.

Also, if you did not create a file in that path, does the godot engine create the file yourself?

Godot will not make a file itself. You will need to create any files you need before you try to read them, otherwise it will not work.

Thankfully, creating files is really easy. I'd check out this page from the documentation on saving/loading files in Godot. It shows how to save and load data using JSON.

Looking at how you are loading scores, if you want to put data into the files so it can be loaded using the code above, then you will need something like this:

func save_highscores():
	var f = File.new()
	f.open(easy_high_path, File.WRITE)
	f.store_var(easy_high_score)
	f.close()
	f.open(hard_high_path, File.WRITE)
	f.store_var(hard_high_score)
	f.close()

Hopefully this helps :smile:

Thank you for answer!

I have read your answers and linked posts

The linked post was hard to read but I followed it with your reply

function and it worked. It seemed that the file was created when I saved it.

I did not understand the json part. I have not studied this part. I'm sorry.

The first time we run it, the value of the variable is null, so we got an error on the part that says json

So I removed the small parts of json and declared zero if the variable is null.

Then I wanted to know where this file was stored.

I wrote user: // so I thought there was a folder named user in the project folder

But there was not. There was no save file in the User folder on drive C.

If you run it again, the saved score will load well.

When I used another engine, I created the above system using the ini file

You could write several variable entries in a single ini file

It looks like your post has something to do with your link.

But it's a little hard to understand because of the for loop.

For the time being, I need to create a file for each variable to be saved.

Then, in time, we'll look for other posts or codes and modify them

Thanks again for your reply. :)

@MungMoong said: I have read your answers and linked posts The linked post was hard to read but I followed it with your reply function and it worked. It seemed that the file was created when I saved it.

I did not understand the json part. I have not studied this part. I'm sorry. Great, I'm glad it worked!

No worries about the JSON part! I just linked it as additional material on how saving/loading works with Godot in case you wanted to read more about it. No reason to apologize or anything, I'm not upset either way, I just thought it might be helpful :smile:

Then I wanted to know where this file was stored. I wrote user: // so I thought there was a folder named user in the project folder But there was not. There was no save file in the User folder on drive C.

user:// changes based on the OS. You can figure out where user:// points by printing the results from the OS.get_user_data_dir() function. I think for Windows it points to Appdata, while in Linux and Mac it points to the Home directory (though I'm not 100% sure).

If you run it again, the saved score will load well. When I used another engine, I created the above system using the ini file You could write several variable entries in a single ini file It looks like your post has something to do with your link. But it's a little hard to understand because of the for loop.

I have not used a ini file programmatically before, but have you looked at Godot's ConfigFile class? It allows you to save and load key value pairs and even has functions for saving/loading data to the filesystem. I'm not sure if it is like a ini file, but maybe it is?

The ConfigFile class as well known and I only recently discovered it, but it looks like it could be useful for storing multiple variables without necessarily having to know the order they are stored in.

For the time being, I need to create a file for each variable to be saved.

That works too. It is not quite as efficient, but for now I'd make the game first, and then if there are problems you can always optimize later.

Then, in time, we'll look for other posts or codes and modify them Thanks again for your reply. :)

Sounds good, and no problem! It's my pleasure!

@TwistedTwigleg ConfigFile is basically INI on steroids, since it supports everything most INI files support (including hand-written comments starting with ;, which will be preserved when the file is saved). Most of Godot's types can be serialized into ConfigFile, including arrays, dictionaries, Colors, Vector2/3…

Still, keep in mind that unlike JSON or YAML, INI is not standardized.

@Calinou said: @TwistedTwigleg ConfigFile is basically INI on steroids, since it supports everything most INI files support (including hand-written comments starting with ;, which will be preserved when the file is saved). Most of Godot's types can be serialized into ConfigFile, including arrays, dictionaries, Colors, Vector2/3…

Still, keep in mind that unlike JSON or YAML, INI is not standardized.

Ah, good to know! I totally didn’t know that you could add comments with ;.

Not to get off topic, but I’m curious: Does ConfigFile serialize to a string or does it serialize to binary like File.store_var? If it serializes to a string, I wonder how much it would differ from the JSON serialization... I suppose I should make a test project and find out :smile:

All in all, very interesting! I really ought to use ConfigFile more often as it seems like there is a lot of potential and it reduces a lot of boiler plate code I normally write when working with save files.

@TwistedTwigleg

Can not json file save multiple items and take out only one?

I'm browsing several posts

However, after putting various values into one dictinary variable, it is saved as json, and only the various values are loaded at once

For example egg = 1 bread = 7 chiken = 11 You can store these values

You can load and save only one variable if you want.(load egg, egg = 3, save egg)

Is only ConfigFile possible?

https://docs.godotengine.org/en/3.0/classes/class_configfile.html And now I'm trying to follow the above post

However, there is an error that a function called get_value is a function that does not exist in 'Node' ↑ I put 'configfile variable name.' At the beginning of the command and the error disappears

close () is also Does not ConfigFile need to use 'close()'?

@MungMoong said:

@TwistedTwigleg

Can not json file save multiple items and take out only one?

I think you can save multiple items and access the one(s) you need. If I recall correctly, the to_json takes a dictionary, and parse_json returns a dictionary. You can retrieve and store items in a dictionary using the square brackets, like dictionary["key_here"] = value_here and value_here = dictionary["key_here"]

I'm browsing several posts

However, after putting various values into one dictionary variable, it is saved as json, and only the various values are loaded at once

For example egg = 1 bread = 7 chiken = 11 You can store these values

You can load and save only one variable if you want.(load egg, egg = 3, save egg)

Sure, you can save and load those variables into a dictionary. It would look something like this (untested):

var json_dictionary = {
	"egg": 1,
	"bread": 7,
	"chicken": 11
}

func _ready():
	save_json();
	json_dictionary["egg"] = 3;
	print (json_dictionary);
	load_json();
	print (json_dictionary);

func save_json():
	var json_string = to_json(json_dictionary);
	var save_file = File.new()
	save_file.open ("user://json_test.json", File.WRITE);
	save_file.store_line(json_string);
	save_file.close();

func load_json():
	var save_file = File.new();
	save_file.open("user://json_test.json", File.READ);
	var json_string = file.get_line();
	save_file.close();
	json_dictionary = parse_json(json_string);

You can also do just one value in the dictionary if you want to save one variable per file.

Is only ConfigFile possible?

https://docs.godotengine.org/en/3.0/classes/class_configfile.html And now I'm trying to follow the above post

However, there is an error that a function called get_value is a function that does not exist in 'Node' ↑ I put 'configfile variable name.' At the beginning of the command and the error disappears

You'll need to call get_file on the ConfigFile object, not just call the function by itself. For example, if your ConfigFile is var save_file = ConfigFile.new() then after you have loaded the data using the load function, you'll need to use something like save_file.get_value("section name here", "key name here") to get the data.

close () is also Does not ConfigFile need to use 'close()'?

I do not think so, I think it handles the saving and load with the save and load functions, unlike File where you have to handle all that yourself.


Hopefully this helps :smile:

var json_string = file.get_line();

I get an error here Parser Error: Identifier not found: file I put this part into the function

If you follow what you told me

The first time you create a save dictionary in a global script, you load the save file.

Then save and reload it whenever you need it, right? :)

My bad. You need to change file.get_line() in the load_json function to save_file.get_line() and that should fix the parse error.

@MungMoong said: If you follow what you told me The first time you create a save dictionary in a global script, you load the save file. Then save and reload it whenever you need it, right? :)

Yup!

You can also use file_exist in the File class if you want to check whether a file exists. Then you can load the file based on whether it exists or not, which means the game will not crash if you get the order wrong, and/or if a user deletes the file then it still will not crash the game.

Something like this should work (untested):

func load_json():
	var save_file = File.new();
	if (save_file.file_exists("user://json_test.json") == true):
		save_file.open("user://json_test.json", File.READ);
		var json_string = file.get_line();
		save_file.close();
		json_dictionary = parse_json(json_string);
		print ("File loaded successfully");
	else:
		print ("Save file does not exist so data could not be loaded");

Hopefully this helps :smile:

@TwistedTwigleg said:

Thank you very much!

I have time to redo my code and fix it.

And I will have time to re-read your posts and docs

As soon as I learned, I was immediately hooked up and there was a lot of code twisted.

I will clean up for the weekend. :)

4 years later