Trying to store the player's current position for a 'save system' I am creating

It would help if you could show me, what that would looke like in code

In the SaveSystem autoload, add the following line at where you initialize you variables(To follow proper guides, put it first, before any @export or var variables)

signal loaded_data

in the load_data function, add the following line to the end. Make sure to put it after you’ve extracted all the data from the JSON file.

loaded_data.emit()

create this function in the player script:

func update_variables_to_data():# The name doesn't need to be exactly this
    global_position=GameData.player_global_position
    # offload all the data in GameData that pertains to the player into the related variables.

finally, connect the function to the loaded_data signal in the _ready() function

SaveSystem.loaded_data.connect(update_variables_to_data)# make sure to update the name here if you decide to change the name of the function mentioned above.

What this does is make the player only use the save_data if the data has been loaded. what I would suggest is that in the load_data function in the autoload, you check if the game data position is in bounds, and only then send the signal.

Instead of trying to fix your stuff, I will explain how I would do it:

Let’s say you have a simple game with just one world.tscn scene, a player.tscn scene and a script game_data.gd autoloaded as GameData.

Let’s first look at the autoloaded script:
game_data.gd

# Let's set the default spawn position to the center of the visible area of the viewport.
# Use whatever position you want as default
var player_global_position = get_viewport().get_visible_rect().size / 2

func load_data():
	... # rest of your code
	var data = JSON.parse_string(content)
	...
	player_global_position = Vector2(data.player_global_position[0], data.player_global_position[1])
	# Look at this above, it expects that player_global_position has this format in the JSON file:
	# { "player_global_position": [333, 555 ] }
func save_data():
	... # rest of your code
	var data = {
		"player_global_position": [player_global_position.x, player_global_position.y]
	}
	# Look at that, it is a lot simpler to save it like this
	...
	}

Now, we attach world.gd to the world scene, so that we can spawn a player.

world.gd

# load the player scene here
var player_scene = preload("res://scenes/player.tscn") 

func _ready():
	spawn_player()

func spawn_player():
	var player_instance = player_scene.instantiate()
	# Now we have an instance of the player scene! Let's set the global_position
	player_instance.global_position = GameData.player_global_position
	# and also add it as a child, so it becomes a Node in the SceneTree
	add_child(player_instance)

See how simple that is?
No signals, no crazy data structures, just easy peasy spawn a player and set the position.
When saving, save the position.
When loading, load the position.

That’s all there is to it.

I did exactly all you said there, I removed var player_global_positon from GameData.gd and moved it over to SaveSystem.gd I changed it into var player_global_position = get_viewport().get_visible_rect().size / 2 and when I start the game it crashes and I get this error messege saying that it is null, and if i keep it like this var player_global_position : Vector2 = Vector2.ZERO and I try to call the load function still nothing happens

At this point I am probably gonna have to try and explain, how my game works

I have this script called base_scene that is attached to world.tscn all levels inherates from it

base_scene.gd

extends Node2D
class_name BaseScene 

@onready var player: Player = $Player
@onready var camera = $FollowCam
@onready var entrance_markers: Node2D = $EntranceMarkers
@export var startingPos: Marker2D


# This input event is for testing.
func _input(event):
	if Input.is_action_just_pressed("retry"):
		respawn_player()

# Called when the node enters the scene tree for the first time.
func _ready():
	player.global_position = startingPos.global_position
	Mediator.base_scene = self
	
	if scene_manager.player:
		if player:
			player.queue_free()
			
		player = scene_manager.player
		add_child(player)
		camera.follow_node = player
		
	position_player()


func position_player() -> void:
	var last_scene = scene_manager.last_scene_name
	if last_scene.is_empty():
		last_scene = "any"
	
	for entrance in entrance_markers.get_children():
		if entrance is Marker2D and entrance.name == "any" or entrance.name == last_scene:
			player.global_position = entrance.global_position


func respawn_player() -> void:
	player.global_position = startingPos.global_position
	player.revive()

In the scene tree

Or even better. Isn’t there a way to save entire current scene state, instead of having to type in all the components you want to save?

when i see people struggling with save and load system, i really recommend to just use plugin like: Save Made Easy - A simple, diverse Save/Load plugin - Godot Asset Library
you can basically Store the player position by saving it like

SaveSystem.set_var("player_position",player.global_position)
SaveSystem.save()

then load the save data easily by just:

SaveSystem.get_var("player_position",Vector2.ZERO)
1 Like

I was beginning to consider, that I should use a plugin instead, because I am feeling trying to create my own save system and having a hard time getting to work, was a waste of time. I might not learn anything from doing so, but in the end all that matters is that, the system works.

I didn’t even mention any SaveData.gd

Glad you got it working.

No you’re mistaken, I didn’t say I manged to get to work, it still dosen’t work

Oh, I thought you got it working with the plugin. Well, anyway to get any more help, I think you may need to shift your attitude a bit more towards gratitude.

1 Like

Yes, using resources.

Look I really do appriciate you trying to help.

Note: If I am say something that sounded spewed, it’s because I have autism, I have trouble with communication

tbh I am out of the loop with how many responses we got.
From what I understand, we got a problem of a dysfunctional system that is unable to properly communicate with its components (especially between Player scene and save resource).

Theoretically, the Save component is most likely part of the Data autoload, you can call it from within the game and because the Player scene is inside of the SceneTree, you can request for the player’s global_position which is a realworld Vector2.

In reality, from the current structure of your code, you are required to always have the correct global position prior to the saving process, in a local instance of GameData inside the Save System script.

Basically, you are required to integrate GameData into your game, then saving the player global_position into player_global_position, either in every process frame or via signal.

  • Example 1: when you click on the Save-button, a signal is send that updates all parameters such as player position. Once the updates are done, you actually execute the save.
  • Example 2: inside _process() you overwrite player_global_position with the current player position.

Doing either should work fine. It’s not perfect but it’s functional and that should be our priority.

That’s exactly how my code checks whether to place the player at a last known position or the starting position.

func _ready():
	var player = get_node("arstronaut")
	if (global.last_position.y != 0):
		player.position.y = global.last_position.y + 20
		player.position.x = global.last_position.x

Bro, did you try my method? I think it works. If you want, here’s a explanation.
What I’m doing is making it so that the load function emits a signal that is connected to a function that sets the players position to the loaded position in Game Data. I forgot to mention it, but the last line of code is supposed to be put in the ready function of the player anywhere you want to put it in.
Edit: This might not work if you follow the changes that @TimothyAlexisVass gave.

Bro from what I read here you need to chill. This guy is obviously new to the system and you just crapped a bunch of information on him. We need to be supporting people, not getting mad when someone new is trying to understand what you have said. It took me weeks to figure out how to do this and I’m still learning, so maybe next time have a little more patience

Quick update, everyone:

I finally managed to get the save system working. Here’s what I did, I ended up reaching out to the Youtuber who made the tutorial, he offered me ways he thinks could work so I tried what what he offered, and after some trial and error I finally got it working, for real this time.

End of this topic.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.