Save and Load variables - how to ? SOLVED THANKS !

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Loxyrak

Hi, I’m trying to save some variables and load them. The saving part works perfectly, but the loading doesn’t.

Here are my 2 scripts Player.GD and SaveAndLoad.gd (which is on autoload)

extends KinematicBody2D

    export (int) var speed = 200
    
    var vel = Vector2()
    var player = SaveAndLoad.player
    var damage : int = 1
    var maxHp : int = 20
    onready var rayCast = $RayCast2D
    
    
    
    
    var xpToNextLevel : int = 50
    var xpToLevelIncreaseRate : float = 1.2
    
    var interactDist : int = 70
    var facingDir = Vector2()
    
    onready var anim = $AnimatedSprite
    onready var ui = get_node("/root/MainScene/CanvasLayer/UI")
    
    
    func _ready ():
        ui.update_textLevel(player["curlvl"])
        ui.update_health_bar(player["curhp"], maxHp)
        ui.update_xp_bar(player["curxp"], xpToNextLevel)
        
    
    func _physics_process(delta):
      vel = Vector2()
      if Input.is_action_just_pressed("attack"):
        try_interact()
      if Input.is_action_just_pressed("save"):
        SaveAndLoad.player = player
        SaveAndLoad.save()
      if Input.is_action_pressed('Right'):
        vel.x += 1
        facingDir = Vector2(1, 0)
      if Input.is_action_pressed('Left'):
        vel.x -= 1
        facingDir = Vector2(-1, 0)
      if Input.is_action_pressed('Down'):
        vel.y += 1
        facingDir = Vector2(0, 1)
      if Input.is_action_pressed('Up'):
        vel.y -= 1
        facingDir = Vector2(0, -1)
            
      vel = vel.normalized() * speed
      vel = move_and_slide(vel, Vector2.ZERO)
      manage_animations()
    
    
    func manage_animations ():
     
        if vel.x > 0:
            play_animation("RunRight")
        elif vel.x < 0:
            play_animation("RunLeft")
        elif vel.y < 0:
            play_animation("RunFront")
        elif vel.y > 0:
            play_animation("RunDown")
        elif facingDir.x == 1:
            play_animation("IdleRight")
        elif facingDir.x == -1:
            play_animation("IdleLeft")
        elif facingDir.y == -1:
            play_animation("IdleUp")
        elif facingDir.y == 1:
            play_animation("IdleDown")
    
    func play_animation (anim_name):
     
        if anim.animation != anim_name:
            anim.play(anim_name)
            
            
    func give_xp (amount):
     
        player["curxp"] += amount
        ui.update_xp_bar(player["curxp"], xpToNextLevel)
        if player["curxp"] >= xpToNextLevel:
            level_up()
     
    func level_up ():
     
        var overflowXp = player["cuxp"] - xpToNextLevel
     
        xpToNextLevel *= xpToLevelIncreaseRate
        player["curxp"] = overflowXp
        player["curlvl"] += 1
        ui.update_level_text(player["curlvl"])
        ui.update_xp_bar(player["curlvl"], xpToNextLevel)
    
    func take_damage (dmgToTake):
     
        player["curhp"] -= dmgToTake
        ui.update_health_bar(player["curhp"], maxHp)
        if player["curhp"] <= 0:
            die()
     
    func die ():
     
        get_tree().reload_current_scene()
        
    func try_interact ():
        
        rayCast.cast_to = facingDir * interactDist 
        
        if rayCast.is_colliding():
            if rayCast.get_collider() is KinematicBody2D:
                rayCast.get_collider().take_damage(damage)
            elif rayCast.get_collider().has_method("on_interact"):
                rayCast.get_collider().on_interact(self)
                
    func _notification(what):
        if (what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST):
            SaveAndLoad.player = player
            SaveAndLoad.save()
            get_tree().quit() # default behavior

SaveAndLoad
extends Node

const FILE_NAME = "user://game-data.json"
var player = {
	"name": "Zippy",
	"curhp": 10,
	"curxp": 10,
	"curlvl": 1
	
}

func _ready():
	SaveAndLoad.load_game()
	
func save():
	var file = File.new()
	file.open(FILE_NAME, File.WRITE)
	file.store_string(to_json(player))
	file.close()


func load_game():
	var file = File.new()
	if file.file_exists(FILE_NAME):
		file.open(FILE_NAME, File.READ)
		var data : Dictionary = parse_json(file.get_line())
		file.close()
		if typeof(data) == TYPE_DICTIONARY:
			player = data
		else:
			printerr("Corrupted data!")
	else:
		printerr("No saved data!")

Like I was saying, the Saving works, the data goes into the file, but when it loads, it goes back to the default I have put in var player.

:bust_in_silhouette: Reply From: Myrmex

In SaveAndLoad.gd, player variable gets updated via load_game function called from _ready function which is executed once the script enters or is instanced from an active scene.
So in Player.gd you assign defaultplayer value before it was processed by any methods.
Either move player = SaveAndLoad.player expression to _ready or call load_game manually from Player.gd before it.