Saving - Loading Project

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

Hello there, i have make a demo project for saving and loading but something goes wrong with the saving it’s overwrite the previous variables and i can’t figure out how to load them. Please help me making the save/load function works.

Link to download the project

When this demo project is done we can add it to demo projects and it will be helpful i think :slight_smile:

:bust_in_silhouette: Reply From: Zylann

Opening a file in WRITE mode truncates it if it exists.
You are saving fruits and vegetables to the same file “saved_game.sav”, that’s why variables get overwritten.

i know it, that’s why i ask help.
Am new to Godot. This is not an answer.

How can i save them to same file?

And what about loading ?

Chr_ | 2016-08-02 13:49

What do you actually expect in the file?

If you don’t want the previous vars to be overwritten, you can save in a different file wether it’s vegetables of fruits.

If you want all in the same file there is the READ_WRITE open mode, which opens the file without truncating it: http://docs.godotengine.org/en/latest/classes/class_file.html
I guess several calls to store_line() produce multiple lines in the file. I’m not familiar with this method in Godot yet because I usually save/load everything at once.

About loading, I made a comment in another post describing a typical savegame process (like the doc shows but simplified), for both save and load: https://forum.godotengine.org/6491/read-%26-write.

EDIT: my bad I noticed it was a post from you. Well… I have to go home, I will edit/post later.

Zylann | 2016-08-02 17:27

:bust_in_silhouette: Reply From: Zylann

I took a look at your project in the editor and it appears you have two problems.
First, you should load the file if it exists and update the GUI when the scene starts:

# Call this function at the end of _ready()
func _load():
	var file = File.new()
	var filename = "user://saved_game.sav"
	if file.file_exists(filename):
		file.open(filename, File.READ)
		fruits.parse_json(file.get_line())
	_update_gui()

func _update_gui():
	get_node("lbl_orange").set_text("Orange: " + str(fruits.orange))
	get_node("lbl_lemon").set_text("Lemon: " + str(fruits.lemon))
	get_node("lbl_pear").set_text("Pear: " + str(fruits.pear))

The second problem is that you are trying to save variables from the second scene in the same file, as if it had no awareness of the other scene.
You have two options:

  1. The other scene can do the same thing but have a different file. This is the simplest given your situation.
  2. Always save and load the whole data
  3. Keep the same unique file and navigate into it.

I personally use 2) if the file is reasonably small, but because your scenes don’t access each other you cannot do it directly, unless you have a singleton holding the variables.

If you want 3), you get a third problem:
How could you recognize which line belongs to which scene in the file?
Well, this is a bit tedious to do with the current API, so that’s why I do 2).
If you really want that, a possible way is to read the file first as a dictionary, modify a part of this dictionary, and save it back. But that’s not much different from saving/loading everything.

Edit: Warning, the following is a bit more advanced and IMO should be only relevant for big files.

It’s a bit easier to do 3) by saving binary data rather than JSON.
Knowing that you have 3 integers to save for each scene, you can save them as 16-bit integers (2 bytes each) with File.store_16(). So using File.seek() you can jump directly to the data you want to read, and read only that without having to parse everything in JSON. So for example, fruits would be in 0, and vegetables in 6 (because 2bytes * 3 = 6).

# Fruits scene
file.store_16(fruits.orange) # Each call to store_16 advances the cursor by 2 bytes
file.store_16(fruits.lemon)
file.store_16(fruits.pear)

# In Vegetables scene, start after vegetables
file.seek(6)
file.store_16(fruits.carrot)
file.store_16(fruits.tomato)
file.store_16(fruits.potato)

# Note: I used store_16 but you could use 8 or 32, it depends what
# is the maximum value you want to store (max 16-bit value is 65536)

Same for loading, you would jump to the correct position and read values with File.get_16() in the same order.

Thank you ! It work’s . i will make two files and store the vars but i will like to know how can i do the second way about my scenes connecting… Anyway thank you for your time and this is an answer :slight_smile:

Chr_ | 2016-08-02 23:54