0
\$\begingroup\$

So I've created a simple main menu with a new game, load game, and quit game buttons. In the new scene where I've created pause menu save/load buttons work, I've created a new object and attached a script to it. So I've used the same logic for the LOAD game button in the main menu, I've created new object and attached script to it and then added that to load button. I then played the game and saved it. I then run the game again and load button didn't work. It didn't output any error or anything.

The script I've used for both load buttons:

using System.Collections.Generic;
using UnityEngine.SceneManagement;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

public class LoadGame : SingletonMonobehaviour<LoadGame>
{
    public GameSave gameSave;

    public List<ISaveable> iSaveableObjectList;

    protected override void Awake()
    {
        base.Awake();

        iSaveableObjectList = new List<ISaveable>(); //create new list for the ISaveableObject list field
    }

    public void LoadDataFromFile()
    {
        BinaryFormatter bf = new BinaryFormatter();
        gameSave = new GameSave();
        FileStream file = File.Open(Application.persistentDataPath + "/SaveData.dat", FileMode.Open);
        gameSave = (GameSave)bf.Deserialize(file);

        //loop through all ISaveable objects and apply save data
        for (int i = iSaveableObjectList.Count - 1; i > -1; i--)
        {
            if (gameSave.gameObjectData.ContainsKey(iSaveableObjectList[i].ISaveableUniqueID))
            {
                iSaveableObjectList[i].ISaveableLoad(gameSave);
            }
            else
            {
                Component component = (Component)iSaveableObjectList[i];
                Destroy(component.gameObject);
            }
        }

        file.Close();
    }

    public void SaveDataToFile()
    {
        gameSave = new GameSave();

        //loop through all ISaveable objects and generate save data
        foreach (ISaveable iSaveableObject in iSaveableObjectList)
        {
            gameSave.gameObjectData.Add(iSaveableObject.ISaveableUniqueID, iSaveableObject.ISaveableSave());
        }

        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Open(Application.persistentDataPath + "/SaveData.dat", FileMode.OpenOrCreate);
        bf.Serialize(file, gameSave);
        file.Close();
    }

    public void StoreCurrentSceneData()
    {
        //loop through all ISaveable objects and trigger store scene data for each
        foreach (ISaveable iSaveableObject in iSaveableObjectList)
        {
            iSaveableObject.ISaveableStoreScene(SceneManager.GetActiveScene().name); //it passes current scene name
        }
    }

    public void RestoreCurrentSceneData()
    {
        //loop through all ISaveable objects and trigger restore scene data for each
        foreach (ISaveable iSaveableObject in iSaveableObjectList)
        {
            iSaveableObject.ISaveableRestoreScene(SceneManager.GetActiveScene().name);  //it passes current scene name
        }
    }
}

So this is the first scene in the game: On Main Menu object there is a script to start new game and to quit the game. I created new object LoadGame that contains the script above.

So  this is the first scene in the game:

This is PauseMenu UI in the game. Basically, players in the game can save/load games and that works normally and as same as I have in the main menu here I too have SaveLoadManager with the script exactly the same (only class name different). I forgot to mention that I created first PersistentScene then I created the MainMenu scene. Maybe the file I save in the game (pause menu) doesn't exist when I press the load button from the main menu. Because If I save the game in the pause menu and load it from there that works.

enter image description here

I have also script GameSave with the following script:

using System.Collections.Generic;

[System.Serializable]

public class GameSave 
{
    //string key = GUID gameobject ID
    public Dictionary<string, GameObjectSave> gameObjectData;

    public GameSave()
    {
        gameObjectData = new Dictionary<string, GameObjectSave>();
    }
}

And ISaveable with the following script:

public interface ISaveable
{
   string ISaveableUniqueID { get; set; }

   GameObjectSave GameObjectSave { get; set; }

    void ISaveableRegister();

    void ISaveableDeregister();

    GameObjectSave ISaveableSave();

    void ISaveableLoad(GameSave gameSave);

    void ISaveableStoreScene(string sceneName);

    void ISaveableRestoreScene(string sceneName);
}
```
\$\endgroup\$
3
  • \$\begingroup\$ It sounds like it's time for you to attach a debugger to Unity and step through the execution of the load method line by line to find our where its execution path differs from what you expect. If you're loading content that's in a different scene from the main menu, what is your current strategy for persisting that loaded information across the scene change? \$\endgroup\$
    – DMGregory
    Feb 9 at 18:13
  • \$\begingroup\$ @DMGregory Hi. Main Menu is a separate scene. I want to load information that I've saved in the pause menu in Scene2 so that when I start the game and click on the load button it will load the game from where it was saved. But the problem probably is that I have saved the game in scene2 and the main menu load button has no save data in it. \$\endgroup\$ Feb 9 at 18:25
  • \$\begingroup\$ Try editing your question to give us enough details about your project setup that we can rebuild a sample of it ourselves, starting from a new, empty project. This is what we call a Minimal Complete Verifiable Example. Once you provide that, we can reproduce your setup and test potential solutions to be sure they'll work for you. \$\endgroup\$
    – DMGregory
    Feb 9 at 18:27
0
\$\begingroup\$

When your code doesn't work, the first thing you should try is usually adding some logging:

    public void LoadDataFromFile()
    {
        Debug.Log("Loading data from file...");
        BinaryFormatter bf = new BinaryFormatter();
        gameSave = new GameSave();
        string path = Application.persistentDataPath + "/SaveData.dat";
        Debug.Log("Opening file " + path);
        FileStream file = File.Open(path, FileMode.Open);
        gameSave = (GameSave)bf.Deserialize(file);

        Assert.IsNotNull(gameSave);
        Debug.Log("iSaveableObjectList.Count: " + iSaveableObjectList.Count);

        //loop through all ISaveable objects and apply save data
        for (int i = iSaveableObjectList.Count - 1; i > -1; i--)
        {
            var id = iSaveableObjectList[i].ISaveableUniqueID;
            if (gameSave.gameObjectData.ContainsKey(id))
            {
                Debug.Log("Loading value for Saveable " + i + " with ID" + id);
                iSaveableObjectList[i].ISaveableLoad(gameSave);
            }
            else
            {
                Debug.Log("No saved data found for Saveable " + i + " with ID " + id);
                Component component = (Component)iSaveableObjectList[i];
                Destroy(component.gameObject);
            }
        }

        file.Close();
    }

I don't see any place that you add values to iSaveableObjectList. Did you forget to populate that list? Does it show up in the Inspector?

\$\endgroup\$
4
  • \$\begingroup\$ Since GameSave is read off of a disc, it's unlikely it contains usable references to ISaveableObjects, since those appear to be a form of component on a GameObject. Unity won't load that kind of content via a BinaryFormatter. \$\endgroup\$
    – DMGregory
    Feb 9 at 21:18
  • \$\begingroup\$ @DMGregory Whoops, I think I misinterpreted some of his code. I need to update my answer. \$\endgroup\$
    – Kevin
    Feb 9 at 21:27
  • \$\begingroup\$ @DMGregory I added images and explained more stuff now. \$\endgroup\$ Feb 10 at 9:47
  • \$\begingroup\$ @Kevin Hi I've used your code and it says " iSaveableObjectList.Count: 0". After the game was saved. Probably save file doesn't exist in this scene and I have somehow to link it from another scene that was saved in. Because the load button works from the pause menu. \$\endgroup\$ Feb 10 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.