Page 1 of 1

ApplyData data is null and GameObjects are not loading

Posted: Sun Feb 20, 2022 5:29 pm
by hidingso
Hello

I ran into a weird issue while restructuring my scene hierarchy.

I am using VS Code with Unity Debugger. My Unity version is 2021.1.17f1 and Dialogue System version is 2.2.18.

I start the game on StartScene, where I have my Dialogue Manager with Menu System and Save System (with PlayerPrefs Saved Game Data Storer).

I start my game and by pressing "Start" I load scene "Player" which acts as a persistent scene in my game, holding the player, camera, lights, and inventory in it.

I then additively load an environment scene based on what needs to be loaded.

When I start my game and pick up some items, they are added to the inventory well ok.
Inventory inventory = GetComponent<Inventory>();
return SaveSystem.Serialize(inventory);
When I save a game, all data seems to be saved properly
SavedGame1: {"m_sceneName":"Player","m_list":[{"key":"AlfonsoPosition","sceneIndex":1,"data":"{\"scene\":5,\"position\":{\"x\":874.1185913085938,\"y\":83.27227783203125,\"z\":-2190.5478515625},\"rotation\":{\"x\":0.0,\"y\":0.266330748796463,\"z\":0.0,\"w\":0.9638817310333252}}"},{"key":"Main Camera","sceneIndex":-1,"data":"{\"scene\":5,\"position\":{\"x\":871.164306640625,\"y\":85.48347473144531,\"z\":-2195.871337890625},\"rotation\":{\"x\":0.05638600513339043,\"y\":0.2501929700374603,\"z\":-0.014597225934267044,\"w\":0.9664424657821655}}"},{"key":"AdditiveSceneManager","sceneIndex":1,"data":"{\"Alfonso\":{\"instanceID\":2032734},\"Airplane\":{\"instanceID\":2032756},\"mainCamera\":{\"instanceID\":2018174},\"playerCam\":{\"instanceID\":2027974},\"BlackFade\":{\"instanceID\":2021468},\"circleTransitionController\":{\"instanceID\":0}}"},{"key":"AddedScenes","sceneIndex":1,"data":"{}"},{"key":"PlayerInventory","sceneIndex":1,"data":"{\"activeBody\":{\"instanceID\":62272},\"activeFront\":{\"instanceID\":0},\"activeTail\":{\"instanceID\":0},\"activeWings\":{\"instanceID\":0},\"activeWheels\":{\"instanceID\":0},\"activePropeller\":{\"instanceID\":0},\"activeMotor\":{\"instanceID\":0},\"items\":[],\"planeParts\":[{\"instanceID\":62260},{\"instanceID\":62262},{\"instanceID\":62264},{\"instanceID\":62266},{\"instanceID\":62268},{\"instanceID\":62270},{\"instanceID\":62272},{\"instanceID\":62274},{\"instanceID\":62276},{\"instanceID\":62278},{\"instanceID\":62280},{\"instanceID\":62282},{\"instanceID\":62284},{\"instanceID\":62286}]}"}]}
But when I try loading the game my Inventory GameObject does not get the data. There is only one Intenvory present in the game.

I tried debugging the ApplyData(string data) method inside the saver, and it seems the "data" string is null. I am not proficcient enough in C# to know if this means that the string is actually empty or the debugger just doesn't see it.

If I go back in the call stack, the Apply Data is called from SaveSystem with what looks like to be the proper SavedGameData

Image

Image

This is puzzling me, why is the data null all of a sudden?

I had the saving/loading working, but I had to refactor some stuff and decided to add the Menu System and Save System that are available on this site.

Re: ApplyData data is null and GameObjects are not loading

Posted: Sun Feb 20, 2022 5:53 pm
by hidingso
Ok,

It seems like the "Save Current Scene" in Save System is the cause of this behavior.

savedGameData has 5 indexes in m_dict, but after line 717 in SaveSystem.cs

Code: Select all

instance.StartCoroutine(LoadSceneCoroutine(savedGameData, null));
m_dict only has 1 index. This is why my data string is null. Is this by design?

I noticed my savers "sceneIndex" variable was different in different savers (although they reside in the same "Player" scene). Does this play a role in the problem? I am wondering if the loading would work if sceneIndexes were different.

Re: ApplyData data is null and GameObjects are not loading

Posted: Sun Feb 20, 2022 8:40 pm
by Tony Li
Hi,

Tick the saver's 'Save Across Scene Changes' checkbox. Otherwise it will save the current scene's index and, if you load a scene that's not that index, it will clear the save data.

Re: ApplyData data is and GameObjects are not loading

Posted: Mon Feb 21, 2022 5:23 am
by hidingso
Tony Li wrote: Sun Feb 20, 2022 8:40 pm Hi,

Tick the saver's 'Save Across Scene Changes' checkbox. Otherwise it will save the current scene's index and, if you load a scene that's not that index, it will clear the save data.
Oh, that seemed to fix it. I thought the "Save Across Scene Changes" would save the data to the current PlayerPrefs slot? Is this incorrect?

Also, if it's ok to ask here: The writing custom savers part doesn't say much about saving references to other classes.

For example

Code: Select all


[Serializable]
public class SomeClass: MonoBehaviour
{
    public AnotherClass another;
}
I have hard time retrieving such references with Loaders, and no idea how to "correctly" serialize references to other objects. Is there some guidelines on how to handle such scenario?

Re: ApplyData data is null and GameObjects are not loading

Posted: Mon Feb 21, 2022 10:16 am
by Tony Li
Hi,

"Save Across Scene Changes" affects the data before it even gets to a SavedGameDataStorer such as PlayerPrefsSavedGameDataStorer. The save system uses it to pare down data that it thinks it no longer needs. Ticking "Save Across Scene Changes" tells the save system that this data should never be cleared out due to a scene change.

Regarding references to other classes, most serializers don't handle references to other classes or other types of UnityObjects (such as ScriptableObjects). The save system's default JsonDataSerializer is no exception.

To save a connection to another class, you'll need to save a basic data type. For example, you could store a unique value such as GUID in AnotherClass:

Code: Select all

public class AnotherClass : MonoBehaviour
{
    public string myGuid;
    
    void Reset() // Unity automatically calls Reset() when adding a script to a GameObject or when resetting it.
    {
        myGuid = System.Guid.NewGuid().ToString();
    }
    
    ... (the rest of your script here)
}
You should serialize MonoBehaviours directly. Use an intermediate class for the save system. Open the PositionSaver.cs class for an example. For example, let's say it's called SomeClassSaveData:

Code: Select all

[Serializable]
public class SomeClassSaveData
{
    public string anotherClassGuid;
}
Your SomeClass can save and load like this:

Code: Select all

public override string RecordData()
{
    var saveData = new SomeClassSaveData();
    saveData.anotherClassGuid = another.myGuid; // (Should really check that another is assigned first.)
    return SaveSystem.Serialize(saveData);
}

public override void ApplyData(string s)
{
    // (Should really check that s isn't empty and that saveData is not null below.)
    var saveData = SaveSystem.Deserialize<SomeClassSaveData>(s);
    
    // Find our AnotherClass by guid:
    foreach (AnotherClass ac in FindObjectsOfType<AnotherClass>())
    {
        if (ac.guid == saveData.anotherClassGuid)
        {
            another = ac;
            break;
        }
    }
}

Re: ApplyData data is null and GameObjects are not loading

Posted: Mon Feb 21, 2022 12:23 pm
by hidingso
Ok, that explains it! Big thanks for the answer!

Re: ApplyData data is null and GameObjects are not loading

Posted: Mon Feb 21, 2022 12:35 pm
by Tony Li
Glad to help!