How to safe CharacterCreator Char and Load on different scenes

Godot Version

Version 4.2.1

Question

I was looking all over Youtube etc. to learn more about saves and loads. But i just cant figure out how to create a save and load feature for my current Character Creator.
For my Character Creator i use two scripts, the first one is for the overlay and changing Sprites
The second one is for the first script to choose the sprites from ( Dictionary )

First Script :
extends Node2D

@onready var bodySprite = $CompositeSprites/Body
@onready var eyesSprite = $CompositeSprites/Eyes
@onready var hairSprite = $CompositeSprites/Hairs
@onready var accessorySprite = $CompositeSprites/Accesory
@onready var mouthSprite = $CompositeSprites/Mouth

var curr_hair: int = 0
var curr_body: int = 0
var curr_eyes: int = 0
var curr_mouth: int= 0

func _ready():
bodySprite.texture = $CompositeSprites.body_spritesheet[curr_body]
eyesSprite.texture = $CompositeSprites.eyes_spritesheet[curr_eyes]
hairSprite.texture = $CompositeSprites.hairs_spritesheet[curr_hair]
mouthSprite.texture = $CompositeSprites.mouth_spritesheet[curr_mouth]

func _on_change_hair_pressed():
SelectSFX.play()
curr_hair = (curr_hair + 1) % $CompositeSprites.hairs_spritesheet.size()
hairSprite.texture = $CompositeSprites.hairs_spritesheet[curr_hair]

func _on_change_body_pressed():
SelectSFX.play()
curr_body = (curr_body + 1) % $CompositeSprites.body_spritesheet.size()
bodySprite.texture = $CompositeSprites.body_spritesheet[curr_body]

func _on_change_eyes_pressed():
SelectSFX.play()
curr_eyes = (curr_eyes + 1) % $CompositeSprites.eyes_spritesheet.size()
eyesSprite.texture = $CompositeSprites.eyes_spritesheet[curr_eyes]

func _on_change_mouth_pressed():
SelectSFX.play()
curr_mouth = (curr_mouth + 1) % $CompositeSprites.mouth_spritesheet.size()
mouthSprite.texture = $CompositeSprites.mouth_spritesheet[curr_mouth]

func _on_return_pressed():
SelectSFX.play()
get_tree().change_scene_to_file(“res://scenes/intro.tscn”)

func _on_done_button_pressed():
get_tree().change_scene_to_file(“res://scenes/game.tscn”)

Second Script:
extends Node

var body_spritesheet = {
0 : preload(“res://assets/CompositeSpritesheets/bodie_1.png”),
1 : preload(“res://assets/CompositeSpritesheets/bodie_2.png”),
2 : preload(“res://assets/CompositeSpritesheets/bodie_3.png”)
}

var hairs_spritesheet = {
0 : preload(“res://assets/CompositeSpritesheets/hair_1.png”),
1 : preload(“res://assets/CompositeSpritesheets/hair_2.png”),
2 : preload(“res://assets/CompositeSpritesheets/hair_3.png”)
}

var eyes_spritesheet = {
0 : preload(“res://assets/CompositeSpritesheets/eyes_1.png”),
1 : preload(“res://assets/CompositeSpritesheets/eyes_2.png”)
}

var mouth_spritesheet = {
0 : preload(“res://assets/CompositeSpritesheets/mouth_1.png”),
1 : preload(“res://assets/CompositeSpritesheets/mouth_2.png”)
}

I tried to save it via ressources and .tres files… but i cant figure out how to set it up and write the right code…

HELP xD

You’re on the right path with trying to use resources, it just sounds like you need help with what to actually do with them.

I will say, I feel like the specifics of your situation don’t matter yet, so I’m going to give a generalized solution. If you have more questions after, feel free to ask.

Create a Custom Resource
To do this, just create a new script.gd and have it extend Resource. Give it a custom class name as well.

Given your needs, I’d recommend calling it class_name CharSpriteSave.

Once you have that, just create variables that your save file will need to be able to load later. Perhaps the curr_feature variables you have in your first script?

Saving Your Custom Resource
Now you have a custom resource. Cool.

To save it, create a new save_sprite_res() function if you don’t have one already.

In this function, you’ll need to create a new instance of your custom resource by assigning CharSpriteSave.new() to a local variable in the function. I’m calling mine new_resource for demonstration.

Start copying all of your variables in the first script to the variables in your resource.

new_resource.curr_hair = curr_hair;
new_resource.curr_body = curr_body;
#etc etc

Finally, save it using the built-in ResourceSaver class.

ResourceSaver.save(“FILEPATHHERE/char_sprite_save.tres”, new_resource);

You can probably guess what this function does by looking at it.

Loading Your Save
If all went well, you should probably have a random file in your folder with your character’s sprite values saved on them. Now we have to suck them back out. This is also pretty straightforward.

Wherever you want to load the data, create a load_sprite_res() function. For demonstration, I’m going to assume you’re loading it in the first script again so you can re-edit your character.

In your loading function just add the line:

var data:CharSpriteSave = load(“FILEPATHHERE/char_sprite_save.tres”);

Now whatever data was in the resource is now in the data variable.

That means you can change the variables in your first script to the ones you had saved before.

curr_hair = data.curr_hair;
curr_body = data.curr_body;
#etc etc

Hope this helped.

2 Likes

I tried to use your advice and im at this point :

extends Resource
class_name CharSpriteSave

var curr_hair: int = 0
var curr_body: int = 0
var curr_eyes: int = 0
var curr_mouth: int = 0
var curr_accessory: int = 0

func save_sprite_res():
var new_resource = CharSpriteSave.new()
new_resource.curr_hair = curr_hair
new_resource.curr_body = curr_body
new_resource.curr_eyes = curr_eyes
new_resource.curr_mouth = curr_mouth

ResourceSaver.save(CharSpriteSave, new_resource)

Problem is i dont get a random file in my res folder…
Maybe i need to add to my " DONE " button in my char Chreator the resourcesaver.save ?

Yes. Have a button that runs the actual function.

ALSO!
Make sure the first parameter of ResourceSaver.save() is a file path, so it knows where to save the folder. If you aren’t sure where, you can have it save to “res://char_sprite_save.tres” temporarily.

So the line would look like ResourceSaver.save("res://char_sprite_save.tres", new_resource).

If all goes well, you should have a new resource file in your root folder named “char_sprite_save.tres”

Okay i see…
So i tried that before and it gives me an error code which says cannot convert argument 2 from Nil to string… + sometimes it says argument 1 has to be ressource but is string
Any clue whats up with that ?
Do i have to create a ressource in my filepath like manually ?

Woopsie daisy.

Switch the two parameters.
ResourceSaver.save(new_resource, "res://char_sprite_save.tres")

Also, I think the way it works is if there isn’t a file with that name, it just adds it. If it finds a file with the same name, it overwrites.

Yeah thats what i tought… i dont get it my project is a whole mess xD
Now its saying “CharSpriteSave” hides a global script class …

Im so thankfullll for your help man, really appreciate.

any suggestion what that error means ? or how to solve it :smiley: