Hello again. I am creating a ‘save system’ for my game, I have followed a tutorial on Youtube, but I can’t figure out how to save the player’s current position in the JSON save file that it creates, I have this ‘GameData’ Script that extends Resource which contains the var Vector2, I am not sure how to assign the player’s current position from the player script to the var Vector2 that is within the GameData script. How I am my supposed to do this?
Save System script, I have this as an autoload
extends Node
const SAVE_DIR = "user://saves/"
const SAVE_FILE_NAME = "save.json"
var game_data = GameData.new()
func _ready():
verify_save_directory(SAVE_DIR)
func verify_save_directory(path : String):
DirAccess.make_dir_absolute(path)
func save_data(path : String):
var file = FileAccess.open(path, FileAccess.WRITE)
if file == null:
print(FileAccess.get_open_error())
return
var data = {
"game_data":{
"player_global_position":{
"x": game_data.player_global_position.x,
"y": game_data.player_global_position.y
}
}
}
var json_string = JSON.stringify(data, "\t")
file.store_string(json_string)
file.close()
func load_data(path : String):
if FileAccess.file_exists(path):
var file = FileAccess.open(path, FileAccess.READ)
if file == null:
print(FileAccess.get_open_error())
return
var content = file.get_as_text()
file.close()
var data = JSON.parse_string(content)
if data == null:
printerr("Cannot parse %s as a json_string: (%s)" % [path, content])
return
game_data = GameData.new()
game_data.player_global_position = Vector2(data.game_data.player_global_position.x, data.game_data.player_global_position.y)
else:
printerr("Cannot open non-existent file at %s!" % [path])
GameData Script
extends Resource
class_name GameData
@export var player_global_position = Vector2.ZERO
Resources are unique. If player_global_position isn’t a static variable that the player updates with their global position, it won’t get your players position of you create a new instance. I would suggest that you have an way for the player to reach the autoload and set an player position variable in the autoload, or use static variables as I mentioned above.
So are you doing anything to put the player position in the variable, or are you just hoping that naming the variable makes it work. I told you some ways to put the players position in the variable above. Static vars are constructed like this
static var player_global_position:Vector2= Vector2.ZERO
without having to instantiate it. Even better, you can access this from any instance or non instance and it will be whatever value you put in it last, no matter what or where you’re instancing it from.
When I press the save input or the save button in the pause menu, i does store the values now. But when I press load nothing happens, it dosen’t place the player in the saved position, what do I need to do inside the load_data function?
So, you need to have some way to take the player global position in the ready function if it is not vector (0,0) (unless (0,0) is the players default spawning point at the beginning of the game.). Basically Timothy’s answer but with an if condition that sets your player to it’s spawning point if the saved position is (0,0) which means the player has not moved. When do you call the load data function? It should preferably be in _init so that you can set all the save data up accordingly when the game starts.
Sorry if I am not getting you. I am still new to Gdscript:
This player.global_position line you are talking about, where am I supposed to put it? In the SaveSystem script?
This where I put it?
func save_data(path : String):
var file = FileAccess.open(path, FileAccess.WRITE)
if file == null:
print(FileAccess.get_open_error())
return
var data = {
"game_data":{
"player_global_position":{
"x": GameData.player_global_position.x, # Here?
"y": GameData.player_global_position.y # Here?
}
}
}
var json_string = JSON.stringify(data, "\t")
file.store_string(json_string)
#file.store_var(player_position)
file.close()
Or here?
func load_data(path : String):
if FileAccess.file_exists(path):
var file = FileAccess.open(path, FileAccess.READ)
if file == null:
print(FileAccess.get_open_error())
return
var content = file.get_as_text()
file.close()
var data = JSON.parse_string(content)
if data == null:
printerr("Cannot parse %s as a json_string: (%s)" % [path, content])
return
GameData.player_global_position = Vector2(GameData.player_global_position.x, # Here?
GameData.player_global_position.y) # Here?
else:
printerr("Cannot open non-existent file at %s!" % [path])
And if I put this in the player _ready() function, when the game starts the player spawns in the top left corner of the map out of bounds and can’t move
0,0 is the top left, and this can be avoided if you check that the position is 0,0 or not. If it isn’t, that means there is savedata, so use the save data. Else use the normal spawning position.
Then you need to make sure that the player knows when the load function is called. Maybe make a signal in the autoload that the player connects to in ready, and the function it connects to makes the players position be the position in the game data. You have to make sure to emit the signal after you load the position in the game data position or else it will load to 0,0.