Daniel Lip
Daniel Lip

Reputation: 11335

How can I access the Save/Load functions from a script that is on another scene?

I have two scene : Main Menu, Game On the Main Menu I have also a two buttons : Save,Load

And two scripts :

Save System :

using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public static class SaveSystem
{
    public static void SavePlayer(Player player)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/player.bin";
        FileStream stream = new FileStream(path, FileMode.Create);

        PlayerData data = new PlayerData(player);

        formatter.Serialize(stream, data);
        stream.Close();
    }

    public static PlayerData LoadPlayer()
    {
        string path = Application.persistentDataPath + "/player.bin";
        if(File.Exists(path))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(path, FileMode.Open);

            PlayerData data = formatter.Deserialize(stream) as PlayerData;
            stream.Close();

            return data;
        }
        else
        {
            Debug.LogError("Save file not found in " + path);
            return null;
        }
    }
}

And Player :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
   public void SavePlayer()
    {
        SaveSystem.SavePlayer(this);
    }

    public void LoadPlayer()
    {
        PlayerData data = SaveSystem.LoadPlayer();

        Vector3 position;
        position.x = data.position[0];
        position.y = data.position[1];
        position.z = data.position[2];
        transform.position = position;
    }
}

The Player script is attached to the Player in the Game scene but now I can't call or get access to the SavePlayer and LoadPlayer from the two buttons in the On Click events.

And another problem is that the Game scene is not all the time in the Hierarchy the Game scene is loaded when I click the Play button and then the Main Menu scene is not loaded and when I hit the escape key it's loading the Main Menu scene but then the Game scene is not loaded.

So I wonder how should I and how can I make a reference between the buttons Save/Load and the functions SavePlayer/LoadPLayer ?

Upvotes: 0

Views: 102

Answers (1)

derHugo
derHugo

Reputation: 90789

After we cleared out that your two scenes are actually not loaded at the same time I would use another approach.

You already have a static class for your loading process. Either there or in a second one you could simply store the player data meanwhile still in the MainMenu. Then the player loads this data on start.

For the active loading and saving from within the game scene you could have another button for the saving.

Something like

public static class SaveSystem
{
    public static PlayerData Data;

    // Without a parameter serialize the values from the current Data
    // which will be updated by the player
    public static void SavePlayer()
    {
        WriteFile(Data);
    }

    public static void SavePlayer(Player player)
    {
        var data = new PlayerData(player);
        WriteFile(data);
    }

    private static void WriteFile(PlayerData data)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/player.bin";
        FileStream stream = new FileStream(path, FileMode.Create);

        formatter.Serialize(stream, data);
        stream.Close();
    }

    public static PlayerData LoadPlayer()
    {
        string path = Application.persistentDataPath + "/player.bin";
        if(File.Exists(path))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(path, FileMode.Open);

            Data = formatter.Deserialize(stream) as PlayerData;
            stream.Close();

            return Data;
        }
        else
        {
            Debug.LogError("Save file not found in " + path);
            return null;
        }
    }
}

Then from the menu

public class MenuButtons : MonoBehaviour
{
    public void Load()
    {
        // Only reads the save file into the SaveSystem.Data
        SaveSystem.LoadPlayer();
    }

    public void Save()
    {
        // Only write SaveSystem.Data to the file
        SaveSystem.SavePlayer();
    }
}

Now in the game scene on the player

public class Player : MonoBehaviour
{
    // Load the player values on startup from SaveSystem.Data
    private void Awake ()
    {
        var data = SaveSystem.Data;

        if(data == null) return;

        Vector3 position;
        position.x = data.position[0];
        position.y = data.position[1];
        position.z = data.position[2];
        transform.position = position;
    }

    // Now it is up to you when and how often you want the player to save its data
    // I would do it e.g. in OnDestroy
    // so everytime the scene is changed
    private void OnDestroy ()
    {
        // Only populates the SaveSystem.Data
        // without necessarily writing the file
        SaveSystem.Data = new PlayerData(this);
    }
}

Upvotes: 1

Related Questions