Open Elmapul opened 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.
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.
Relevant: #946.
yes i didnt meant it need an completely rewrite. thanks!
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())
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.
Some issues cropped up recently over on the discord, summarizing them here:
for i in save_nodes: var node_data = i.call("save"); save_game.store_line(to_json(node_data))
var node_data = i.call("save");
could be reduced to var node_data = i.save()
, which is also more in line with general GDScript stylenew_object.position = Vector2(current_line["pos_x"], current_line["pos_y"]))
has an extra parenthesis )
at the end, throwing syntax errors when copy/pasted"user://savegame.save"
while loading attempts to check for "user://save_game.save"
's existence before trying to load "user://savegame.save"
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()
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.
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
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()
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
@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.
That's a 404 not found link. What did it do?
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))