Understanding saving(and loading)

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

(I’ve modified my question)

If I just want to save/load only custom variables inside of children nodes?
Whenever I load, all the variable in my nodes are reset. I want to keep their current values.

If they’re being set to 0 after loading, the loading’s working but the saving isn’t, are you saving via json, cfg or txt?

Magso | 2020-03-28 18:06

I’m saving via Json, when I check the save document in notepad, only some of the variables are there, but the load isn’t using them. The other variables are being ignored in the save. I’m not sure why.

Dumuz | 2020-03-28 18:12

Have you followed these examples? Saving to a dictionary and storing it in a json then loading using get_line() for the correct order of nodes.

Magso | 2020-03-28 18:29

Yes, I’ve been following that specific documentation this whole time.
I checked the save file the code generates and it does, in fact, save all the variables.(I just didn’t realize they were out of order from my listed dictionary.)

But it’s still not loading the variables. It just kind of resets everything. He’s the script i’m using:

func _load_game():
	var save_game = File.new()
	if not save_game.file_exists("res://savegame.save"):
		print("error, dont have a file to load")
		return
	var save_nodes = get_tree().get_nodes_in_group("Persist")
	for i in save_nodes:
		i.queue_free()
	save_game.open("res://savegame.save", File.READ)
	while save_game.get_position() < save_game.get_len():
		var node_data = parse_json(save_game.get_line())
		var new_object = load(node_data["filename"]).instance()
		get_node(node_data["parent"]).add_child(new_object)
		new_object.translation = Vector3(node_data["pos_x"], node_data["pos_y"], node_data["pos_z"])
		for i in node_data.keys():
			if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
				continue
			new_object.set(i, node_data[i])
	save_game.close()

Dumuz | 2020-03-28 18:36

The for loop at the bottom is unchanged from the example, has your dictionary got the exact same key names?

Magso | 2020-03-28 18:51

For the most part yes. I did just add the “pos_z” to the load script.

func save():
	var save_dict = {
		"filename": get_filename(),
		"parent": get_parent().get_path(),
		"pos_x": translation.x,
		"pos_y": translation.y,
		"pos_z": translation.z,
		"global_year": year,
		"global_month": month,
		"global_day": day,
		"global_minute": minute,
		"global_sec": sec,
     }
     return save_dict

Dumuz | 2020-03-28 18:55

I can’t see why this wouldn’t be working, the only other thing I can think of is that the variable names of the nodes don’t match the key names so

new_object.set(i, node_data[i])
#which is like
new_object.key_name = node_data["key_name"]

isn’t working.

Magso | 2020-03-28 19:33

As a diagnosing measure, I placed a random print in place of the new_object.set(i, node_data[i]) portion of the script and it doesn’t print anything. Confirming that if statement is the culprit somehow.

 if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":

So, I took out the if statement under the for statement and it updates the variables as intended. But I honestly don’t know why this statement would stop it from iterating through the rest of the keys.

Dumuz | 2020-03-28 20:36

:bust_in_silhouette: Reply From: Haikala

I had the same issue using the sameish code. The values were saved, but they were applied in the wrong order of what the loaded node wanted them in.

I managed to make it work by adding the child lastly in the load list so that anything in the ready() function was going to use the right data. I’m still very much learning and i haven’t quite figured out how to set up the node for receiving the load data in a better way. i hope this helps anyone and makes sense :smiley:

save_map.open("user://savemap.save", File.READ)
while save_map.get_position() <save_map.get_len():
	var node_data = parse_json(save_map.get_line())
	var new_object = load(node_data["filename"]).instance()
	
	#moved add child from here
	
	new_object.position = Vector2(node_data["pos_x"], node_data["pos_y"])
	
	print(node_data)
	#for other variables after:
	for i in node_data.keys():
		if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
			continue
		new_object.set(i,node_data[i])
	
	# to here
	get_node(node_data["parent"]).add_child(new_object)
	
save_map.close()

I have a an custom initalization function that I call in the _ready() of the parent if I want it to run after the parent finished with assigning values and whatnot. Might help

PeterA | 2021-11-08 13:43