Is there a way to save a texture or do I need multiple variations of 1 item?

Godot Version

4.2

Question

So I have a key node that I use for multiple keys and I all I do is just change the exported variable for the key sprite and key name. However I have run into an issue where if I save and load the game the key will either revert back to its default sprite or not have a sprite at all. However if I make a new key node with the new sprite as its default then its fine cause its a different node but same script.

So now Im wondering if I need to make multiple different key nodes with the new sprite or is there a way to save the texture so that I can load it back up?

I am using the godot save and load tutorial here so like im saving it into the whole json file thing: Saving games — Godot Engine (stable) documentation in English

You can use custom resources and save/load them.

How would I go on about this because I saw a tutorial on custom resources but i am confused as to how to go on and save the resource?

Depends on how you are saving and loading the game. Are you saving the key’s texture after it’s changed?

I am saving the key with all the changed textures but when I load the game the keys texture changes back to the default texture that i made the node with and not with the texture that i changed it to.

You will have to paste some code for this, devil is in the details. How are you saving the key’s texture?

This is how I am saving it. Its the item picture variable.

I have also tried:
sprite_2d.texture
making a texture2d variable and saving that and loading it back in the ready function
making a resource variable and saving that and loading it back in the ready function

func Save():
	var dict = {
		"filename" : get_scene_file_path(),
		"parent" : get_parent().get_path(),
		"posX" : self.position.x,
		"posY" : self.position.y,
		"isPickedUp" : isPickedUp,
		"keyName" : keyName,
		"ItemPicture" : $sprite_2d.texture.resource_path,
		"Picture" : Picture
	}
	return dict

And how are you loading the resource_path? Do you get any errors?

I am loading everything back through a json file.

I dont get any errors, its just the texture just changes back to the default texture as though the texture i am saving isnt actually being saved.

Without the scripts or errors to go on it’s hard to say. There is no reason for it to change texture outside of what you are tell it to do through scripts and animations.

I dont think it will help but here is the saving and loading system i made with the godot tutorial. All it does go get the nodes in saveobjects group in this case which are the keys and call the save function so it writes all the information in the dictionaries into a json file and load everything in that json file.

func SaveGame():
	var file = FileAccess.open(saveFile, FileAccess.WRITE)
	#SAVE THE CURRENT SCENE------------------
	#var data = {
		#"savedCurrentScene" = get_tree().get_current_scene().scene_file_path
	#}
	
	#file.store_var(data)
	#-----------------------------------
	
	#SAVE OBJECTS---------------------
	var saveNodes = get_tree().get_nodes_in_group("SaveObjects")
	print(saveNodes)
	for nodes in saveNodes:
		if nodes.scene_file_path.is_empty():
			print("Node '%s' is not instantiated and will be skipped" % nodes.name)
			continue
		if !nodes.has_method("Save"):
			print("Node '%s' doesnt have a save function and will be skipped" % nodes.name)
			continue
		var nodeData = nodes.call("Save")
	
		var jsonString = JSON.stringify(nodeData)
		file.store_line(jsonString)
	#-------------------------------------------------
	
	print("Curent Scene Saved" + get_tree().get_current_scene().name)
	print("Game was Saved")
	
func LoadGame():
	get_tree().reload_current_scene()
	await get_tree().create_timer(0.04).timeout
	if not FileAccess.file_exists(saveFile): #if the file doesnt exist
		SaveGame()
		
	var file = FileAccess.open(saveFile,FileAccess.READ)
	
	#LOAD SCENE------------------------------------------------
	#var savedata = file.get_var()
	#currentScene = savedata.savedCurrentScene
	##file = null
	#get_tree().change_scene_to_file(currentScene)
	#--------------------------------------------------------------
	
	#LOAD OBJECTS-------------------------------------------------------
	var saveNodes = get_tree().get_nodes_in_group("SaveObjects")
	print(saveNodes)
	#print("commence node deletiono")
	for nodes in saveNodes:
		#print(nodes.name + " theres a node")
		nodes.queue_free()
		print("objects deleted")
		#await nodes.tree_exited
	#print("node deletetion finished")
	while file.get_position() < file.get_length():
		var json_string = file.get_line()
		var json = JSON.new()
		var parse_result = json.parse(json_string)
		if not parse_result == OK:
			print("JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line())
			continue
			
		var nodeData = json.data
		var new_object = load(nodeData["filename"]).instantiate()
		get_node(nodeData["parent"]).add_child(new_object)
		new_object.position = Vector2(nodeData["posX"], nodeData["posY"])
		for i in nodeData.keys():
			if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
				continue
			new_object.set(i, nodeData[i])
	#file = null
	#----------------------------------------------------------------------------
	print("Game was Loaded")

Cool this is it, you are not loading the texture change.

Notice the for loop skips over keys filename, parent, pos_x, and pos_y? That’s because they are unique cases that were handled above. You will need to do the same for ItemPicture as it’s not a basic member, like isPickedUp or keyName is just a member variable.

"isPickedUp" : isPickedUp, # just a member
"keyName" : keyName, # just a member

# a child node's property two resources deep, very complex
"ItemPicture" : $sprite_2d.texture.resource_path, 

You will have to load the resource then apply it to the new object’s sprite_2d child. While we are here let’s add more warnings for data that was loaded but unused.

var new_object = load(nodeData["filename"]).instantiate()
get_node(nodeData["parent"]).add_child(new_object)
new_object.position = Vector2(nodeData["posX"], nodeData["posY"])

# Load picture resource
var item_picture = load(nodeData["ItemPicture"])
if item_picutre:
	new_object.get_node("sprite_2D").texture = item_picture
else:
	push_warning("Couldn't load ItemPicture: ", nodeData["ItemPicture"])

# Load basic members
for i in nodeData.keys():
	if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y" or i == "ItemPicture":
		continue
	if i in new_object: # check member exists
		new_object.set(i, nodeData[i])
	else:
		push_warning("Couldn't set member %s in node %s." % [i, nodeData["filename"]])
2 Likes

OMG This Worked! I was honestly starting to prepare myself to make a bunch of key nodes with different textures. I did have to change “sprite_2D” to Sprite2D because I forgot sprite_2D was the name of the variable and not the actual node name.

I understand so much now