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()
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)
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.
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 overwriteplayer_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.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.