فهرست منبع

Improvements in "Saving Games" tutorial

- Check for common errors and display error messages (node not instanced, missing save function)
- Proper logic for checking there's a line left when iterating through the save file
- Extra comments and different variable names to make the code more clear
PouleyKetchoupp 5 سال پیش
والد
کامیت
ca886ca062
1فایلهای تغییر یافته به همراه48 افزوده شده و 19 حذف شده
  1. 48 19
      tutorials/io/saving_games.rst

+ 48 - 19
tutorials/io/saving_games.rst

@@ -136,8 +136,21 @@ way to pull the data out of the file as well.
         var save_game = File.new()
         save_game.open("user://savegame.save", File.WRITE)
         var save_nodes = get_tree().get_nodes_in_group("Persist")
-        for i in save_nodes:
-            var node_data = i.call("save");
+        for node in save_nodes:
+            # Check the node is an instanced scene so it can be instanced again during load
+            if node.filename.empty():
+                print("persistent node '%s' is not an instanced scene, skipped" % node.name)
+                continue
+            
+            # Check the node has a save function
+            if !node.has_method("save"):
+                print("persistent node '%s' is missing a save() function, skipped" % node.name)
+                continue
+            
+            # Call the node's save function
+            var node_data = node.call("save")
+            
+            # Store the save dictionary as a new line in the save file
             save_game.store_line(to_json(node_data))
         save_game.close()
 
@@ -155,7 +168,24 @@ way to pull the data out of the file as well.
         var saveNodes = GetTree().GetNodesInGroup("Persist");
         foreach (Node saveNode in saveNodes)
         {
+            // Check the node is an instanced scene so it can be instanced again during load
+            if (saveNode.Filename.Empty())
+            {
+                GD.Print(String.Format("persistent node '{0}' is not an instanced scene, skipped", saveNode.Name));
+                continue;
+            }
+            
+            // Check the node has a save function
+            if (!saveNode.HasMethod("Save"))
+            {
+                GD.Print(String.Format("persistent node '{0}' is missing a Save() function, skipped", saveNode.Name));
+                continue;
+            }
+            
+            // Call the node's save function
             var nodeData = saveNode.Call("Save");
+            
+            // Store the save dictionary as a new line in the save file
             saveGame.StoreLine(JSON.Print(nodeData));
         }
 
@@ -190,20 +220,20 @@ load function:
         # Load the file line by line and process that dictionary to restore 
         # the object it represents.
         save_game.open("user://savegame.save", File.READ)
-        while not save_game.eof_reached():
-            var current_line = parse_json(save_game.get_line())
-            if current_line == null:
-                continue
+        while save_game.get_position() < save_game.get_len():
+            # Get the saved dictionary from the next line in the save file
+            var node_data = parse_json(save_game.get_line())
             
             # Firstly, we need to create the object and add it to the tree and set its position.
-            var new_object = load(current_line["filename"]).instance()
-            get_node(current_line["parent"]).add_child(new_object)
-            new_object.position = Vector2(current_line["pos_x"], current_line["pos_y"])
+            var new_object = load(node_data["filename"]).instance()
+            get_node(node_data["parent"]).add_child(new_object)
+            new_object.position = Vector2(node_data["pos_x"], node_data["pos_y"])
+            
             # Now we set the remaining variables.
-            for i in current_line.keys():
+            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, current_line[i])
+                new_object.set(i, node_data[i])
         save_game.close()
 
  .. code-tab:: csharp
@@ -228,20 +258,19 @@ load function:
         // it represents.
         saveGame.Open("user://savegame.save", (int)File.ModeFlags.Read);
 
-        while (!saveGame.EofReached())
+        while (saveGame.GetPosition() < save_game.GetLen())
         {
-            var currentLine = (Dictionary<object, object>)JSON.Parse(saveGame.GetLine()).Result;
-            if (currentLine == null)
-                continue;
+            // Get the saved dictionary from the next line in the save file
+            var nodeData = (Dictionary<object, object>)JSON.Parse(saveGame.GetLine()).Result;
 
             // Firstly, we need to create the object and add it to the tree and set its position.
-            var newObjectScene = (PackedScene)ResourceLoader.Load(currentLine["Filename"].ToString());
+            var newObjectScene = (PackedScene)ResourceLoader.Load(nodeData["Filename"].ToString());
             var newObject = (Node)newObjectScene.Instance();
-            GetNode(currentLine["Parent"].ToString()).AddChild(newObject);
-            newObject.Set("Position", new Vector2((float)currentLine["PosX"], (float)currentLine["PosY"]));
+            GetNode(nodeData["Parent"].ToString()).AddChild(newObject);
+            newObject.Set("Position", new Vector2((float)nodeData["PosX"], (float)nodeData["PosY"]));
 
             // Now we set the remaining variables.
-            foreach (KeyValuePair<object, object> entry in currentLine)
+            foreach (KeyValuePair<object, object> entry in nodeData)
             {
                 string key = entry.Key.ToString();
                 if (key == "Filename" || key == "Parent" || key == "PosX" || key == "PosY")