I've been looking at save game tutorials (example) lately, and it seems that a popular way to save the game is to create dictionaries that contains all the information that needs to be saved, and when the save is loaded, the dictionary is first loaded from the file and then the corresponding in game objects are adapted/created based on the dictionaries.

However, I feel like these tutorials are somewhat detached from how real games work. A very simple example is the position of an object. For example, if your 2D game has a number of NPCs that can wander around a map, when you load that map you need to load the positions of the NPCs as well, and using the methods these tutorials taught, what you need is to save the position of each NPC as entries in the dictionary e.g.: x = 100, y = 200. And when you load the game you need to find these entries from the dictionary and do something like: NPC.global_position = Vector2(dictionary.x, dictionary.y)

Somehow that just feels wrong. Like, surely there is a way to easily save the built-in data of some node2Ds, maybe the entire Node2D instance can be saved instead of having its individual components saved? Maybe there is even some brute force method to save the entire game state instead of having to create huge/nested dictionaries.

So I'm asking for less general advice and more personal experience on how you handle your own game's save system. Especially for games with more physics-like environments rather than abstract state machines like a visual novel.

    GE100

    Maybe there is even some brute force method to save the entire game state instead of having to create huge/nested dictionaries.

    You can achieve that by using PackedScene, but I wouldn't recommend it. As soon as anything in your node structure changes the save file becomes out-of-date, so it's very fragile.
    You can also serialize entire instances with inst2dict (or inst_to_dict in Godot 4), but I think if you plan on storing large amounts of data, the best way would be to create a Godot resource and save it as .res (binary resource format). Of course you still need some serialization/deserialization code, but not as much as you have with dictionaries if you structure your code right.

    I use text strings. afile.store_line(String(var))
    I would write a function in the npc script, func writetofile(afile):
    then I would have a master save script in the level which calls those functions on all npc's.
    Also in reverse order, func readfromfile(afile): using the int(afile.get_line()) or float(afile.get_line()) functions.
    This makes your save files very hackable, which is desired by lots of gamers. Not all though.

    GE100 I've been using JSON without much trouble. honestly, the kind of permanence you're looking at is work, more or less, but the function is simple, as with any program, just repeated as much as you need it, or as little if you're a really GOOD programmer. Reminder that first-generation Pokemon LITERALLY almost crashed GameFreak's computers back in the day while they tested it.

    This boils down to data structures to be sure and how you use them. Currently, for my event system, if you want something less complex, I just start with an empty array in globals, slap an export key : String and check if values are there. If they are, event doesn't go and if they aren't, the event fires and adds its "key." Then you're only saving an array. Stuff like this can save you some work.

    I'm glad to see y'all's comments but I still feel kinda lost.

    From the sound of things there are no magic bullet solution to save a generic Node instance. Instead, it sounds like manual, use-case-specific code still has to be written for each atom of information that needs to be save/loaded, including built-in stuff like global_position

    If you are searching for a system that works semi-automatically, you could use another approach I've used. Create a "ToSave" node group that has a save and load method, or exposes a list of members that should be saved. Then you use call_group or iterate over the nodes and collect the save data into a Godot resource / JSON file / etc. On load you pass the saved data back to the nodes.

      GE100

      I created one with a more generic solution:

      SaveGameDemo.zip

      In this project you can add Savable nodes to nodes you want saved. Then you can change the list of properties that should be saved.