Safest and easiest way to save high scores

Ver 4.3

I know basically nothing about saving in Godot, but I’m seeing some things saying some methods of saving are dangerous, and I just want to know how to save a high score, so here is my question: What is the safest and easiest way to save high scores in Godot?

1 Like

There are some examples here, even with a high score and it’s probably the best.
"or using the generic store_var(), which will use Godot’s built-in serialization to encode your data, including complex data like objects.
https://kidscancode.org/godot_recipes/4.x/basics/file_io/

3 Likes

tbh I’m not exactly sure how the code is setup for what you’ve sent me. Should all of the code be in one script? What should be in the “user://” part?

In “user://” you need to write the file name like “saveFile”(that will be the file’s name in your game’s folder) and then the file format like .png(in this case .save or .bin).

1 Like

Saving files in code? I haven’t heard of this in Godot, but I guess that’s how it would work. So you don’t make anything else for it, you just make the name and everything in a script right? And this data can be accessed by all scripts once it’s put in one?

the easiest way to “encode” highscores
use var_to_bytes() on dictionary with scores

var dict:={"leader":12345}
var bad_byte=111
bad_byte=var_to_bytes(bad_byte)
var bad_byte_size:int=bad_byte.size()
var bytes:=var_to_bytes(dict)
bytes.append(bad_byte)
bytes.reverse()
bytes=bytes.compress(1)

now its lightly encrypted bytes, remember somewhere bad_byte_size
save it using FileAccess

to make it back readable:

var bytes:PackedByteArray=load(user://score.bin)
bytes=bytes.decompress_dynamic(-1,1)
bytes.reverse()
bytes.resize(bytes.size()-bad_byte_size)
var dict:Dictionary=bytes_to_var(bytes)

So this should just be in my main scene script, right?
If it wouldn’t be too hard, could you please do a quick break down of what the script does and how it works?

Their example doesn’t save to a file. It would help if you described what data you want to save, the specific variable types and format.

Overall you will want to use FileAccess.

Here’s an example saving and loading one high score

const SAVE_PATH = "user://highscore.bin"

func save_highscore(highscore: int) -> void:
	var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
	if file:
		file.store_64(highscore)
	else:
		push_warning("Couldn't save highscore file: ", error_string(FileAccess.get_open_error()))


func load_highscore() -> int:
	var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
	if file:
		return file.get_64()
	else:
		push_warning("Couldn't load highscore file: ", error_string(FileAccess.get_open_error()))
		return -1

A lot of people convert to JSON because it is readable, thus easy to debug or edit manually, have you read the tutorial from the official docs?

1 Like

What is the .bin ?

format *.bin means binary data or raw bytes

1 Like

1. Find a place to store data.

Written at the first, the data shouldn’t stored at code part, unless if you want the player to take their game copy in a flash disk or you want to make a self-extract file. Also most packed result will not allow to write to code such as .apk or .pck.

  • Local file or cookies.
  • Network server.
  • Some hardware(if you want only to run it at a specified platform).

2. Find way to access that.

For example, local file needs FileAccess accessing user://.
And the network server needs HTTP accessing a network position hosted by you or someone.
The hardware storage needs a way to access that device such as OS.exec("echo 'some data' >> /dev/ttyUSB0")(really unsafe for injecting).

3. Writing them in code.

You should make some method named get/set_high_score or sth like in your code to access it easily.
And make sure you can’t read the score when you are writing it.

@ComiCross, I am working on the same thing today. This tutorial can show you through video some of the things people are referencing here. It might not solve all your problems, but it might expand a bit on what you are seeing here, or help drive home the points.

Good luck.

1 Like

Thank you! I think it might be working, but I can’t test because it won’t let me call the SaveLoad.save_highscore() func in my main code. I added this to make the Save script available

const SaveLoad = preload('res://Save.gd')

but this just pops up with an error:

SaveLoad.save_highscore()

The func appears to be fine

func save_highscore():
	var file = FileAccess.open(SAVEFILE, FileAccess.WRITE_READ)
	file.store_32(high_score)
	file = null

The one thing in the video I didn’t know what he was doing was when he said to go to the project settings and do something, but he didn’t go to the project settings and show what to do. I also don’t think he had the preload script that I added to my main one, so if you happen to know what I’m doing wrong, please tell me, thank you :slight_smile:

1 Like

So he made the scene an Autoload and yes he missed showing you that.

Essentially, you go to Project → Project Settings → Globals Tab → Click on the file icon next to the Path Field → select the save_load.gd script → Click +Add

It should look like this:

Here is documentation on Autoloads: Singletons (Autoload) — Godot Engine (stable) documentation in English

It makes a scene or script load in first before anything else and be available across all scenes. Have you ever had trouble passing information from one scene to another? Or a scene couldn’t access a particular node or information you want to give to that scene (like a highscore!)? Odds are you need an Autoload of some kind.

This really tripped me up when I started, and I use them all the time now.

2 Likes

THANKS SO MUCH!! It looks like I finally got the high score working.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.