Saving and loading game and a skin of a player

Godot Version

4.3

Question

I have a game where the player can buy/change skin for his avatar. I’ve created the shop interface and everything works as I planned. Problems start with saving and loading it through my savegame binaries. Other stats are being saved and loaded perfectly (all of them are straight number values) but this texture change for player’s Sprite2D doesn’t work.

I use Autoloads for the “skin-related stuff”:

@onready var player_skin = $"../World/Player/Sprite2D"
const PLAYER_DEFAULT = preload("res://asstets/art/player_default/player_default.png")
const PLAYER_GREEN = preload("res://asstets/art/player_green/player_green.png")
const PLAYER_PURPLE = preload("res://asstets/art/player_purple/player_purple.png")

Shop interface changes player_skin.texture to one of those three above.

And now I save/load things using this code:

func save_game():
	var file = FileAccess.open("res://savegame.dat", FileAccess.WRITE)
	file.store_var(ManagerVar.max_hp)
	file.store_var(ManagerVar.current_hp)
	file.store_var(ManagerVar.cash)
	file.store_var(ManagerVar.kill_count)
	file.store_var(ManagerVar.death_count)
	file.store_var(ManagerVar.mission_count)
	file.store_var(ManagerVar.max_engine_power)
	file.store_var(ManagerVar.SpeedUpgradeLvl)
	file.store_var(ManagerVar.HpUpgradeLvl)
	file.store_var(ManagerVar.player_skin)
	file.close()

func load_game():
	var file = FileAccess.open("res://savegame.dat", FileAccess.READ)
	ManagerVar.max_hp = file.get_var()
	ManagerVar.current_hp = file.get_var()
	ManagerVar.cash = file.get_var()
	ManagerVar.kill_count = file.get_var()
	ManagerVar.death_count = file.get_var()
	ManagerVar.mission_count = file.get_var()
	ManagerVar.max_engine_power = file.get_var()
	ManagerVar.SpeedUpgradeLvl = file.get_var()
	ManagerVar.HpUpgradeLvl = file.get_var()
	ManagerVar.player_skin = file.get_var()
	file.close()

Aaaand it doesn’t work for the skin part. What’s the problem here? What I’m doing wrong? Any ideas?

how is this not throwing an error? look at the console.
if this is an autoload, you can’t access a node, and doing .. should not work because autoloads exist above the scene in the tree.
you can click remote on the tree while running your game and see for yourself.
also, autoloads load first so this node should not exist at that time.

and this doesn’t seem very safe for in-app purchases. you can go to the user folder of your game and open the text file and see its contents (and edit it). you should do this now to make sure the correct values are being written.

also, not much is shown here that would help diagnose the problem. or what the problem is. does it just do nothing?

you can press the remote button on the tree while running your game and select the nodes to check if things are being changed.

Well, it works and there’s no error in the debugger. Based on the Remote tree I did navigation as I imagine it should work (see the arrows). The shop works and the skin is changed while in game and in theory I can save game. When I restart the game and select load, it doesn’t do anything with the skin. Loads all other variables as intended and it doesn’t change the skin.

image

It’s not an in-app purchase with real money but ingame currency (like gold). Maybe it’s a bad attitude but I don’t care whether a player will cheat or not.

I assume that crucial info here is your tip “autoloads load first so this node should not exist at that time”. I’ll try to move the whole “skin” thing to the player script and save it from there somehow.

I’ve found out a solution which might not be pretty and optimal (can’t tell since I’m newbie) but it seems to work:

I moved the whole “skin” stuff out of the autoloads leaving there a variable for current skin value. When the player buys/changes a skin in the shop, it sets the global current skin value to 0, 1 or 2 (depending on the chosen skin). Now, when the game is loaded, an IF statement checks this global skin value and changes player’s skin accordingly.

Would love to know whether it’s okay’ish or the whole concept should be burned to the ground :slight_smile: