I have a setup where i save through writing into a cfg file. Stupid probably, but I cant see if dict saving would be different. Maybe someone can elaborate on how to do this feasibly?
.
I start by this:
var health
#imagine having 200 vars here
.
to save i do this:
var savefile = ConfigFile.new()
savefile.set_value("data","health", health)
#imagine having 200 vars here
savefile.save(savefile_main)
.
to load i do this:
var savefile = ConfigFile.new()
savefile.load(savefile_main)
health = savefile.get_value("data","health",100.0)
#imagine having 200 vars here
.
ok, imagine having 200 vars to saveâŚ
I end up writing names of variables many many times. I wish i could do it in a way where i only had to sort of register an item once, and then i could iterate over the items when i save the whole bunch, when i load the whole bunch,
if only it was sane to do a str_to_var thing (which i know it isnt!)
im not quite sure what exactly you want, but have you looked at the ResourceSaver? It allows you to saves resources, which can contain hundreds of variables, easily
# The dictionary syntax itself if you never used one:
var game_data = {
"health": 100.0,
"mana": 50.0,
"level": 1,
"position": Vector2(120,20)
# ... more variables
}
# Saving
func save_game():
var savefile = ConfigFile.new()
for key in game_data.keys():
savefile.set_value("data", key, game_data[key])
savefile.save(savefile_main)
If you really do have a great number of class-body variables you can use get and set along with an array of strings denoting which variables to save. Though this doesnât leave much room for failure conditions.
const TO_SAVE = [
"health", "money", "coins",
"copper", "gold", "dabloons",
"cash", "dollars", "gp",
]
func save() -> void:
var savefile = ConfigFile.new()
for var_name in TO_SAVE:
savefile.set_value("data", var_name, get(var_name))
savefile.save(savefile_main)
func load() -> void:
var savefile = ConfigFile.new()
savefile.load(savefile_main)
for var_name in TO_SAVE:
set(var_name, savefile.get_value("data", var_name)
Thereâs reasons to not use resources for data serialization, such as for networked games and shareable assets where it could open up a remote code execution vulnerability. Otherwise, use custom resources. They are great.
Example:
class_name YourData extends Resource
@export var health = 0xDEAD
@export var max_stamina = 100
# ---
# Some other place:
const data_path = "user://your_data.tres"
var your_data
func load_data():
if ResourceLoader.exists(data_path):
your_data = load(data_path)
else:
your_data = YourData.new()
func save_data():
assert(your_data != null)
ResourceSaver.save(your_data, data_path)
Alternative
A more advanced alternative is to use get_property_list(). Filter out your script properties. Serialize those properties to config file, json, etc. And then the inverse.
To access the data in a dictionary you simply do this:
game_data["health"]
So for the example you used:
func check_coins(game_data: Dictionary):
print("You have %d coins." % game_data["coins"])
Of course, in a real game scenario to not risk crashes, I would employ a safe way to check if the key exists to grab errors, like here:
func check_coins(game_data: Dictionary):
if game_data.has("coins"):
print("You have %d coins." % game_data["coins"])
else:
print("You have no coins in your game data!")
hey sorry for being a pest. I would then change a value in a key by doing this?(scavenging from multiple other posts and sites for thisâŚ):
#Adding ONE coin to the wallet
#"savedata" is the savedata dictionary
var current_coins = savedata.get["coins",0]
savedata["coins"] = current_coins + 1
#Or even better? ------->
savedata["coins"] = savedata.get("coins",0) + 1
@export var savefile_data : String #set to "data.cfg" in editor
var data_slotname = "data"
##Dictionary holding the data!
#Values are just defaults.
var data = {
"health": 100.0,
"energy": 0.0,
"damage": 0,
"mumu": 0,
"luck": 0.0,
"goodwill": 0.0,
"bla bla":0
#keep going, keep going!
}
.
.
Saving the entire dictionary
func save_playerdata():
print("Savemanager - Saving all playerdata!")
var savefile = check_savefile(savefile_playerdata)
for key in data.keys():
savefile.set_value(playerdata_slotname, key, data[key])
print("Savemanager - Saving key:",key," : ",data[key])
savefile.save(savefile_playerdata)
.
.
Loading the values from the dictionary (whatever it may contain)
func load_playerdata():
print("Savemanager - Attempting load all playerdata!")
var savefile = check_savefile(savefile_playerdata)
savefile.load(savefile_playerdata)
if !savefile.has_section(playerdata_slotname):
print("Savemanager - Savefile does not have contents. Will be made via the savemanger at begin!")
return
for key in data:
print("Savemanager - Loading all playerdata!")
var value = savefile.get_value(playerdata_slotname, key)
data[key] = value
print("Savemanager - Loading key:",key," : ",data[key])
.
.
.
.
.
Aaaannnnd this function to ease the boiler-plating
func check_savefile(savefile_to_check):
var savefile = ConfigFile.new()
var err = savefile.load(savefile_to_check)
if err != OK:
print("Savemanager - Loading ", savefile_to_check,"failed!")
return null
return savefile