Page 1 of 2

SaveSystem.loadEnded is not invoking

Posted: Sun Jul 02, 2023 6:54 am
by Fitbie
Hey!

I have a simple class that sends the UnityEvent onGameLoadNDataApplied; to all initializators when the game has loaded + savedataapplied. However, after a few tests, I noticed that this event doesn't work, and I saw through the console that there was a problem with loadEnded.

Code: Select all

    [SerializeField] private UnityEvent onGameLoadNDataApplied;
    private bool loadedSavedGame; //Is game loaded?
    

    private void Start() 
    {
        SaveSystem.loadEnded += () => Debug.Log("Savesystem LoadEnded");
        SaveSystem.loadEnded += OnLoadEnded;
        SaveSystem.saveDataApplied += () => Debug.Log("Savesystem DataApplied");
        SaveSystem.saveDataApplied += OnSaveDataApplied;
        Debug.Log("Subscribed to SaveSystem events");
    }

    private void OnLoadEnded()
    {
        Debug.Log("Game loaded");
        SaveSystem.loadEnded -= OnLoadEnded;
        loadedSavedGame = true;
    }

    private void OnSaveDataApplied()
    {
        if(loadedSavedGame)
        {
            SaveSystem.saveDataApplied -= OnSaveDataApplied;
            Debug.Log("Save data applied");
            onGameLoadNDataApplied.Invoke();
        }
    }
I didn't change the source code (except that I made my own TransitionManager:SceneTransitionManager, and also added a bool to the Selector component to keep track of the state).
By the way I think this class used to work, but to be honest I never tested it until today

UPD
In case somebody has same problem, you need to find public static void LoadFromSlot(int slotNumber) SaveSystem.cs method and delete if (loadStarted.GetInvocationList().Length > 1) check, and (as i understand) also delete else{ LoadFromSlotNow(slotNumber);}

Re: SaveSystem.loadEnded is not invoking

Posted: Sun Jul 02, 2023 7:07 am
by Fitbie
I investigated and found that the problem with this method in SaveSystem.cs

Code: Select all

        private static void NotifyLoadEndedWhenSceneLoaded(string sceneName, int sceneIndex)
        {
            Debug.Log("NotifyLoadEndedWhenSceneLoaded");
            sceneLoaded -= NotifyLoadEndedWhenSceneLoaded;
            loadEnded();
        }
Its called from public static event SceneLoadedDelegate sceneLoaded = delegate { };
And this fella called from this method

Code: Select all

        private void FinishedLoadingScene(string sceneName, int sceneIndex)
        {
            m_currentSceneIndex = sceneIndex;
            if (!m_isLoadingAdditiveScene)
            { // Don't delete other non-cross-scene data if loading additive scene:
                m_savedGameData.DeleteObsoleteSaveData(sceneIndex);
            }
            m_isLoadingAdditiveScene = false;
            sceneLoaded(sceneName, sceneIndex);
        }
I checked and FinishedLoadingScene working correctrly. So its seems the problem is sceneLoaded delegate. But i dont understand why

UPD: I did this:

Code: Select all

sceneLoaded += (stringName, sceneIndex) => Debug.Log($" sceneLoaded: {stringName} + {sceneIndex}");
And there is nothing in console. I guess smth wrong with this delegate in my project?🤔

Re: SaveSystem.loadEnded is not invoking

Posted: Sun Jul 02, 2023 8:10 am
by Tony Li
I confirmed that the events work correctly. Is something in your project unregistering sceneLoaded?

Note: There are two sceneLoaded events:
  • Unity's UnityEngine.SceneManagement.SceneManager.sceneLoaded
  • SaveSystem script's sceneLoaded
In your project, is SaveSystem.NotifyLoadEndedWhenSceneLoaded() being called? Try putting a breakpoint in that method.

Re: SaveSystem.loadEnded is not invoking

Posted: Sun Jul 02, 2023 8:37 am
by Fitbie
I update my 2nd reply, so
im talking about this sceneLoaded

Code: Select all

public static event SceneLoadedDelegate sceneLoaded = delegate { };
this does nothing:

Code: Select all

sceneLoaded += (stringName, sceneIndex) => Debug.Log($" sceneLoaded: {stringName} + {sceneIndex}"); //Delete
This method isnt working, i see nothing in Log console:

Code: Select all

        private static void NotifyLoadEndedWhenSceneLoaded(string sceneName, int sceneIndex)
        {
            Debug.Log($"NotifyLoadEndedWhenSceneLoaded {sceneName} + {sceneIndex}");
            sceneLoaded -= NotifyLoadEndedWhenSceneLoaded;
            loadEnded();
        }
sceneLoaded called by method FinishedLoadingScene
And this method working correctly, i see Log message in console:

Code: Select all

        private void FinishedLoadingScene(string sceneName, int sceneIndex)
        {
            m_currentSceneIndex = sceneIndex;
            if (!m_isLoadingAdditiveScene)
            { // Don't delete other non-cross-scene data if loading additive scene:
                m_savedGameData.DeleteObsoleteSaveData(sceneIndex);
            }
            m_isLoadingAdditiveScene = false;
            Debug.Log("FinishedLoadingScene");
            sceneLoaded(sceneName, sceneIndex); // <--- This guy does nothing
        }
That means UnityEngine.SceneManagement.SceneManager.sceneLoaded working good, bc this is the root call. Broken chain here is event SceneLoadedDelegate sceneLoaded. But how?
Im about to go crazy

Re: SaveSystem.loadEnded is not invoking

Posted: Sun Jul 02, 2023 10:06 am
by Tony Li
I found a case where loadEnded() might not be called. This patch should fix it. This fix will also be in version 2.2.39.

DS_SaveSystemPatch_2023-07-02.unitypackage

Re: SaveSystem.loadEnded is not invoking

Posted: Mon Jul 03, 2023 7:34 am
by Fitbie
There is some problem :(
Image

Re: SaveSystem.loadEnded is not invoking

Posted: Mon Jul 03, 2023 8:49 am
by Tony Li
Can you back up your project and update to the current Dialogue System version?

Re: SaveSystem.loadEnded is not invoking

Posted: Tue Jul 04, 2023 12:27 pm
by Fitbie
Okay, now my mind is really about to blow.

I tried to check: does SaveSystemEvents.cs invoking OnLoadEnd() UnityEvent. So i add there couple Debug.Logs and ofc i added SaveSystemEvents.cs component, empty SaveSystemEvents component, so all of my logic still subscribed to SaveSystem.public static event SceneLoadedDelegate sceneLoaded = delegate { };, not to SaveSystemEvents

And now - everything is working! But i dont understand: hows that? I mean, SaveSystemEvents does literally nothing except calling bunch of UnityEvents, and im not even subscribed to them, im subscribed to root SaveSystem delegate event
I'm really in love with delegates, events, actions, funcs, etc., so now im scared - maybe i don't understand smth? Could you please help me to figure it out?

But i have 1 guess in my mind - all of your scripts is in a "Plugins" folder. As i know plugins have a different compilation order. But still - i don't understand, they have to compile first, and only then my own scripts will subscribe to your delegate events. Even more - all of my Debug.Logs that i put in your SaveSystem.cs - are working too, but they haven't until i add SaveSystemEvents.cs.
And the other thing - actually i didn't know that you have to initialize delegates, like

Code: Select all

delegate void = {}
I tried to delete initialization, but it didnt help, even worse - i had NullReferenceException, so it means that sceneLoaded delegate is called first, and even SaveSystem.cs methods like NotifyLoadEndedWhenSceneLoaded() dont have time to subscribe to sceneLoaded delegate. Also i subscribe anonimous Debug.Log before sceneLoaded() call - and it works great. But i still don't understand - how empty SaveSystemEvents fix that, some voodoo magic?

Re: SaveSystem.loadEnded is not invoking

Posted: Tue Jul 04, 2023 2:35 pm
by Tony Li
You don't have to initialize delegates. But initializing them means you don't have to check for null. So you can do this:

Code: Select all

public System.Action someEvent = null;
...
if (someEvent != null) someEvent();
// or:
someEvent?.Invoke();
Or you can do this:

Code: Select all

public System.Action someEvent = delegate {};
...
someEvent();
As for SaveSystemEvents, try removing it. Does everything still work? I can't think of any reason why an empty SaveSystemEvents would make things work.

Re: SaveSystem.loadEnded is not invoking

Posted: Tue Jul 04, 2023 3:57 pm
by Fitbie
Thanks for tips!

About events: yeah, i remove it - nothing works. I add back - everuthing is okay. Blow my head.

Ill attach my version of scripts:
https://dropmefiles.com/gtccL