godotengine / godot-docs

Godot Engine official documentation
https://docs.godotengine.org
Other
3.94k stars 3.22k forks source link

Fix the documentation (saving games) for godot 3 #427

Open Elmapul opened 7 years ago

Elmapul commented 7 years ago

Sorry if that sounds like duplicated from: https://github.com/godotengine/godot/issues/9984 but i realized i had posted at the wrong place, here is the correct place to post this issue.

Operating system or device - Godot version: Ubuntu 14.04 Godot 3.0 alpha

I was following this tutorial: http://docs.godotengine.org/en/latest/learning/features/misc/saving_games.html and got this error: Invalid call. Nonexistent function 'to_json' in base 'Dictionary'. i took me a while to figure out that insted of:

savegame.store_line(nodedata.to_json()) i should do that: savegame.store_line(to_json(nodedata))

stillinthe90s commented 7 years ago

Sorry for digging this up again, but I still don't think the code works that well... (unless free() works differently in later 2.1.x & 3.0) As discussed here, the code's load function produces an increasing number of clone nodes. I don't know why the author never fixed it. It probably just needs to be complemented with some weakref() checks, but I'm not confident enough to do that myself.

NathanLovato commented 7 years ago

The article does need a complete rewrite, and a demo to download. It could use a few improvements:

And gotta update it for 3.0. Until someone gets to rewrite it, I made 2 video tutorials myself, with MIT licensed code examples.

mhilbrunner commented 6 years ago

Relevant: #946.

Elmapul commented 6 years ago

yes i didnt meant it need an completely rewrite. thanks!

Nomys commented 6 years ago

Hi !

There is a problem in the 'func load_game' of the exemple :

while not save_game.eof_reached(): var current_line = parse_json(save_game.get_line())

Now we set the remaining variables.

    for i in current_line.keys():
        if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
            continue
        new_object.set(i, current_line[i])

This isn't working (i've cut the exemple because I only need to save variables not nodes for now). The error is that the function 'keys()' isn't found for the array.

Solution is to replace 'var current_line = parse_json(save_game.get_line())' with : var current_line = parse_json(save_game.get_as_text()). We also need to remove the 'while not save_game.eof_reached():' line or we'll get a crash. It allows to access the values just with a 'current_line.filename' path.

PetePete1984 commented 6 years ago

Some issues cropped up recently over on the discord, summarizing them here:

Personal suggestion for a rewrite: don't store single objects as JSON lines in the file, store an object in total (like a dictionary with a save_data: [ object1, object2.. ] structure) to leverage get_as_text()

Silenoid commented 6 years ago

Windows 10, Godot Engine v3.0.1 stable official:

The only problem I have is the _getfilename() call, wich seems to return no valid data. I couldn't find any trace of the methon on the most recent version of Godot so I've tried other methods to get the so called "filename" and still not getting any good result. Without that very function, the whole process of saving Nodes and loading them in trees makes the document a bit misleading, even if I understood everything I should have done, but as I'm reading these posts I understand I should find a better source :) Thanks everyone for the infos.

slawo1605 commented 5 years ago

This thread helped me a lot, I also used an excellent tutorial by @NathanLovato and moved his code to version 3.06, so hope people will find it useful as I basically added the entire working project in Godot (I am quite new to this, so hope this is the right way to do this) https://github.com/slawo1605/Godot-3-Save-Load-Example

wish-22 commented 4 years ago

(Disregard comment.)

I'm new to Godot too and I still keep getting the "keys" error. I've used a lot of sources and I'm not sure if it's a newbie mistake.

var levels = {
    l_001 = 0,
    l_002 = 0,
    l_003 = 0,
    l_004 = 0,
    l_005 = 0,
    l_006 = 0,
    l_007 = 0,
    l_008 = 0,
}
func _ready():
    # Skipped over some other code...

    # File prep
    load_game()
func load_game():
    var save_game = File.new()
    if not save_game.file_exists(saveslot):
        return # Error! We don't have a save to load.

    # We need to revert the game state so we're not cloning objects
    # during loading. This will vary wildly depending on the needs of a
    # project, so take care with this step.
    # For our example, we will accomplish this by deleting saveable objects.
    var save_nodes = get_tree().get_nodes_in_group("Persist")
    for i in save_nodes:
        i.queue_free()

    # Load the file line by line and process that dictionary to restore
    # the object it represents.
    save_game.open(saveslot, File.READ)
    var data = {}
    data = parse_json(save_game.get_as_text())
    for node_path in data.keys():
        var node_data = data[node_path]
        get_node(node_path).load_state(node_data)
    save_game.close()
ghost commented 3 years ago

I think using JSON for saving in the only saving tutorial is a bad idea. It tricks people into thinking that they should only use JSON to save stuff. Case in point: this QA question: https://godotengine.org/qa/96501/storing-opensimplexnoise-in-a-file-and-loading-it-back-in

Calinou commented 3 years ago

@ShatReal See https://github.com/godotengine/godot-demo-projects/pull/517. The Saving games tutorial still needs to be rewritten to take this new demo into account.

ghost commented 3 years ago

That's a 404 not found link. What did it do?