Need help to figure out how to save and load in my game

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Atomic Potato

I have been working with Godot for a couple of weeks now and I am new to game development. I decided that I wanted to make an interactive comicbook as my first proper game, and I have figured everything out so far as scene switching and I have even made a stat system for the player script, and now I only need to make a save system. I have read the Docs on save games, but as I said I am pretty new to Godot and gamedevelopment so it is a hard concept for me to grasp. I have made it so every page has its own scene so when you make a choice by pressing a button you switch page/scene, so what I want to do is to make a save and load system that remembers what scene you came to so when you press the continue button on the frontpage it loads the last page that you were on, any help or examples on how would be very much appreciated.

:bust_in_silhouette: Reply From: Eric Ellingson

So this is kind of what I use for loading/saving to a save file:

extends Node

func save_data(save_path : String, data : Dictionary) -> void:
    var data_string = JSON.print(data)
    var file = File.new()
    
    var json_error = validate_json(data_string)
    if json_error:
        print_debug("JSON IS NOT VALID FOR: " + data_string)
        print_debug("error: " + json_error)
        return

    file.open(save_path, file.WRITE)
    file.store_string(data_string)
    file.close()

func load_data(save_path : String = "user://game.dat"):
    var file : File = File.new()
    
    if not file.file_exists(save_path):
        print_debug('file [%s] does not exist; creating' % save_path)
        save_data(save_path, {})
    
    
    file.open(save_path, file.READ)
    
    var json : String = file.get_as_text()
    var data : Dictionary = parse_json(json)
    
    file.close()
    
    return data

What I think you should do is just save something like {"last_scene_path": "res://path/to/scene.tscn"} whenever you load a new scene. Then, when you press the continue button, do something like:

var game_data = load_data()
some_method_to_change_scene(game_data.last_scene_path)

Why isn’t any identifier of load_data() suggested?
Example: I want to do score = load_data().score and after the dot nothing is suggested, in this case “score”.

MaaaxiKing | 2020-05-03 21:53

I want to save more than one data in this dictionary. How do I do that? If I do save_data("user://game.dat", {"score" : score}) and save_data("user://game.dat", {"highscore" : highscore}), just one “object” is saved because the save_data function overrides instead of adding a line for every new “object”.

MaaaxiKing | 2020-05-03 22:32

save_data("user://game.dat", {"score" : score, "highscore": highscore})

Eric Ellingson | 2020-05-04 03:57

If you’re setting the values from a different place, then you’ll have to use a different approach. I would change the save_data method to something like this:

func save_data(save_path : String, new_data : Dictionary) -> void:
    # merge data into existing save data
    var all_data = load_data(save_path)
    for key in new_data.keys():
        all_data[key] = new_data[key]

    var data_string = JSON.print(all_data)
    var file = File.new()

    var json_error = validate_json(data_string)
    if json_error:
        print_debug("JSON IS NOT VALID FOR: " + data_string)
        print_debug("error: " + json_error)
        return

    file.open(save_path, file.WRITE)
    file.store_string(data_string)
    file.close()

Eric Ellingson | 2020-05-04 04:04

Thanks a lot. Is it possible each object to have its own line in the file?
Example:
{“score”:10,
“highscore”:30}

MaaaxiKing | 2020-05-04 10:00

How can I save something in a different dictionary but in the same file and how to add an array and its values?
Example: {“score”:10,“highscore”:30},{“held_items”:[“sword”,“axe”,“bow”]} I don’t know if the array is in quotations too.

MaaaxiKing | 2020-05-04 13:55

I can do:

var held_items_array = []
save_data("user://game.dat", {"held_items" : held_items_array.append("axe")})

That works but can I do something like that without initializing/declaring an array before? I want to do this in just one line. save_data("user://game.dat", {"held_items" : ["axe"]}) or anything in kind of this way didn’t work, as I expected.

MaaaxiKing | 2020-05-06 12:07

My file looks kind of so:
{“1”:{“a”:“hello”,“b”:[“bye”,“paper”]},“2”:{“material”:“glass”}}
Your solution doesn’t work anymore now. What do I have to do?

MaaaxiKing | 2020-05-20 12:09

What does all_data[key] = new_data[key] exactly do?

MaaaxiKing | 2020-05-21 12:12

Is it possible to do nothing if the wanted key doesn’t exist without doing in every single script for every key this:

if load_data(user://game.dat).has("any_key"):
do_something()

I want to check for every wanted key if it exists in the save-load-script and if it doesn’t it shouldn’t do anything with it.

MaaaxiKing | 2020-05-23 10:04

Is there a way to synchronize the variables and the file, so if I do first_var = 1, I don’t have to do save_data("user://game.dat",{"first_var":1}) (or save_data("user://game.dat",{"first_var":first_var})) to have the same value at both places?

MaaaxiKing | 2020-06-02 15:21

How to save something on Android? So what path must I need?

MaaaxiKing | 2020-06-18 10:32