I had a problem when I try to load data of my game in Godot 4.2

Godot Version

Godot 4.2

Question

Hi, I have a question, why when I try to load data of my game, the game doesn’t load data in the GUI? For example, I have a inventory within my game but the player data is saved, the problem is generated when I try to load this inventory in the inventory GUI; my code is the following:

extends Node

var user_filename = "user://save_game.dat"

func save_data():
	var player_data = {
		"coins": Global.coins,
		"lifes": Global.health_rabbit,
		"levels_gained": Global.levels_gained,
		"inventory": Inventory.inventory
	}
	var save_file = FileAccess.open(user_filename, FileAccess.WRITE)
	save_file.store_var(player_data)
	save_file = null
	
func load_data():
	if FileAccess.file_exists(user_filename):
		var save_file = FileAccess.open(user_filename, FileAccess.READ)
		var player_data = save_file.get_var()
		print(player_data)
		save_file = null

Another thing to note is that in my code the player data is manually saved and load, for example:

func select_rabbit():
    SaveGame.load_data() # This code line calls a SaveGame autoload with their load data function 
    Transition.change_scene("res://Scenes/Levels/level_1.tscn") # This code line calls an autoload called Transition to change the level of the player 

My question is: How can I solve this problem in my code so that the GUI is updated when the game loads? Thanks for read this topic!

There is different way to achieve this but I need more information :

  • Is the entire scene changing ?
  • How your GUI look like in the scene tree and where is it compared to this node ?

You’re loading the data into a local variable in load_data(), then discarding the local variable when load_data() is done.

You have not shown any code that updates your GUI.

1 Like

Answers:

  • No, just change the score, lifes and inventory items of the player.
  • Here I show you the GUI of the SceneTree:

The problem is that when I create a dictionary for the player data, I get an error that it says:

The "coins" identifier doesn't recognized.

“coins” is a variable of the Global autoload, and I try to reference this variable of the following way:

var player_data: Dictionary = { 
    "coins": Global.coins,
    "lifes": Global.health_rabbit,
    "levels_gained": Global.levels_gained,
    "inventory": Inventory.inventory
}

How can I solve this error when I want to create this dictionary in my SaveGame autoload?

So it’s a problem with your Global autoload. Can you show us it’s code ?

Of course, I show us my Global autoload code:

extends Node

var select_character: int = 0
var select_weapon: int = 0
var health_rabbit: int = 100
const rabbits_to_instance: Array[PackedScene] = [
	preload("res://Scenes/Characters/jumpy.tscn")
]
var levels_gained = 0

var damage: int
var isWon: Dictionary = {
	"isWonEnemy": false,
	"isWonRabbit": false
}
var isDamaged: bool = false
var bullet: PackedScene = preload("res://Scenes/bullet.tscn")
var coins: int = 0
var playerisDied = false
var isLost: Dictionary = {
	"Rabbit": false,
	"Enemy": false
}

const levels: Dictionary = {
	"level1": preload("res://Scenes/Levels/level_1.tscn")
}

const weapons: Array[Texture2D] = [
	preload("res://Graphics/Inventory/Items/misil.png"), 
	preload("res://Graphics/Inventory/Items/rabbit_bomb.png"),
	preload("res://Graphics/Inventory/Items/shield.png")
]

What is in your function “save_file.get_var()” ?

Seems like you still need to load the player_data back into the globals. save/load have a mirrored chirality, loading must do everything saving does, but mirrored.

func load_data():
	if FileAccess.file_exists(user_filename):
		var save_file = FileAccess.open(user_filename, FileAccess.READ)
		var player_data = save_file.get_var()
		print(player_data)
		save_file = null
		Global.coins = player_data["coins"]
		Global.health_rabbit = player_data["lifes"]
		Global.levels_gained = player_data["levels_gained"]
		Global.inventory = player_data["inventory"]

Then you can update your GUI

I put on the player_data dictionary in Global autoload, but once I ran the game, I got the following error: Invalid get index ‘inventory’ (on base: ‘Dictionary’).That’s right, I initialize the variable in my SaveGame autoload

Could you paste the problematic line?

Ok, I will do it right away

I got the following error “Invalid get index ‘coins’ (on base: ‘Nil’).”, for the following dictionary:

var player_data: Dictionary = {
	"coins": Global.coins,
	"lifes": Global.health_rabbit,
	"levels_gained": Global.levels_gained,
	"inventory": InventoryShow.inventory
}

Just in case, this dictionary I declared it before creating the save and load functions.

How is Global defined? If it’s an autoload like before then is this player_data defined in the class body or inside a function? It can’t get information about the autoload before it’s _ready, maybe a @onready would suffice, but this will copy most of the data like ints, float, and booleans; which wont be very useful.

Yes, Global autoload is defined, but now I deleted the player_data dictionary from the Global autoload, is now back in SaveGame autoload.

var select_character: int = 0
var select_weapon: int = 0
var health_rabbit: int = 100
const rabbits_to_instance: Array[PackedScene] = [
	preload("res://Scenes/Characters/jumpy.tscn")
]
var levels_gained = 0

var damage: int
var isWon: Dictionary = {
	"isWonEnemy": false,
	"isWonRabbit": false
}
var isDamaged: bool = false
var bullet: PackedScene = preload("res://Scenes/bullet.tscn")
var coins: int = 0
var playerisDied = false
var isLost: Dictionary = {
	"Rabbit": false,
	"Enemy": false
}

const levels: Dictionary = {
	"level1": preload("res://Scenes/Levels/level_1.tscn")
}

const weapons: Array[Texture2D] = [
	preload("res://Graphics/Inventory/Items/misil.png"), 
	preload("res://Graphics/Inventory/Items/rabbit_bomb.png"),
	preload("res://Graphics/Inventory/Items/shield.png")
]

Another thing, when I try to save and load the player inventory, the inventory is empty, the inventory items are Resources, but when they are saved and load, in the terminal shows me that the inventory objects are EncodedObjects, they aren’t resources

Inventories might need some clever tricks to be saved.

Ok, I understand you, changing the subject, now I got the following problem with the code line: InventoryShow.inventory = player_data["inventory"], the error is the following:

Is that due to the same thing you say? Another question, which methods can I use to save and load inventories with Godot 4.2?

Depends on how your inventory works. I might store a dictionary with keys as the resource file path and values being the count of said item in the inventory, rather than using the resources directly. This only works if you never edit the item resources, like “durability” loss when used.

1 Like