Save System: Custom saver applied twice for no apparent reason

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
NotVeryProfessional
Posts: 145
Joined: Mon Nov 23, 2020 6:35 am

Save System: Custom saver applied twice for no apparent reason

Post by NotVeryProfessional »

I have a custom saver that for reasons I can't figure out is applied TWICE to my scene, with obvious not desireable results.

The saver is definitely present only once in the scene and in the save file, and the call stack is directly from SaveSystem:

Code: Select all

BlackForest.VillageSaver:ApplyData (string) (at Assets/0_game/Scripts/Savers/VillageSaver.cs:119)
PixelCrushers.SaveSystem:ApplySavedGameData (PixelCrushers.SavedGameData) (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:674)
PixelCrushers.SaveSystem/<LoadSceneCoroutine>d__111:MoveNext () (at Assets/Plugins/Pixel Crushers/Common/Scripts/Save System/SaveSystem.cs:785)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) (at /Users/bokken/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:189)
LoadScene also definitely gets called only once. Everything else appears to work (SaveSystem loads the correct scene, applies all other savers correctly, etc.)

I'm staring at the source and can't for the life of me figure out why it is calling ApplyData() two times. The two calls have the same timestamp, but from my debug output I see that the first one is applied entirely before the second one is called, so they're called one after the other, not in parallel.

Also, the debug output from line 770 in SaveSystem.cs:

Code: Select all

            if (debug) Debug.Log("Save System: Loading scene " + savedGameData.sceneName +
appears only once in my console. That one leads up to the

Code: Select all

ApplySavedGameData(savedGameData);
call, so that's not duplicated, either.

I suspect the culprit somewhere near Line 674. For whatever reason the SaveSystem thinks it has this saver twice, maybe?


My custom saver is set up with Append Saver Type true and Save Across Scene Changes true.
NotVeryProfessional
Posts: 145
Joined: Mon Nov 23, 2020 6:35 am

Re: Save System: Custom saver applied twice for no apparent reason

Post by NotVeryProfessional »

Adding debug outpot to SaveSystem like this:

Code: Select all

        /// <summary>
        /// Applies the saved game data to the savers in the current scene.
        /// </summary>
        /// <param name="savedGameData">Saved game data.</param>
        public static void ApplySavedGameData(SavedGameData savedGameData)
        {
            if (savedGameData == null) return;
	        m_savedGameData = savedGameData;
	        Debug.Log(m_savers);
	        foreach (Saver s in m_savers) {
	        	Debug.Log("saver: "+s+" with key "+s.key);
	        }
            if (m_savers.Count <= 0) return;
            for (int i = m_savers.Count - 1; i >= 0; i--) // A saver may remove itself from list during apply.
            {
                try
                {
                    if (0 <= i && i < m_savers.Count)
                    {
	                    var saver = m_savers[i];
	                    Debug.Log("apply data to saver "+saver+" at position "+i+" with key "+saver.key);
                        if (saver != null) saver.ApplyData(savedGameData.GetData(saver.key));
                    }
                }
                catch (System.Exception e)
                {
                    Debug.LogException(e);
                }
            }
            saveDataApplied();
        }

results in revealing that SaveSystem finds my saver twice - at position 20 and 25. However in the first debug (the list) it appears only once. So my conclusion is that the issue is in the for loop after that. I do have some gameobjects that could possibly despawn immediately after init, taking the saver with them. Looking at the debug output it looks like everything between positions 31 and 25 gets applied twice.

That's as far as I can dig in. The deeper workings of the SaveSystem elude me further.

Here's the console from that:
Bildschirmfoto 2021-12-23 um 10.20.14.png
Bildschirmfoto 2021-12-23 um 10.20.14.png (251.84 KiB) Viewed 695 times
User avatar
Tony Li
Posts: 21981
Joined: Thu Jul 18, 2013 1:27 pm

Re: Save System: Custom saver applied twice for no apparent reason

Post by Tony Li »

Hi,

Did you tick your saver's 'Restore On Start' checkbox? If so, it will apply data in Start() as well as when the Save System would normally apply data on a scene change or saved game load.

If that doesn't help, can you confirm that the SaveSystem.m_savers list has two copies of your custom saver? If so, does your scene perhaps have two instances of your custom saver component?
NotVeryProfessional
Posts: 145
Joined: Mon Nov 23, 2020 6:35 am

Re: Save System: Custom saver applied twice for no apparent reason

Post by NotVeryProfessional »

Neither of those. "Restore on Start" is false, I've verified the saver is in the scene only once, and when I Debug.Log the savers list just before the loop, it contains this saver only once.


I found the line that makes the difference:

Code: Select all

		public override void ApplyData(string m_data) {
			Debug.LogError("VillageSaver starting up...", gameObject);
			if (string.IsNullOrEmpty(m_data)) return;
			var villageData = SaveSystem.Deserialize<VillageData>(m_data);
			if (villageData == null) return;

			// clear out the village, so we don't get duplicates
			foreach (Transform child in transform) {
				BuildingController BC = child.GetComponent<BuildingController>();
				if (BC != null) {
					//Destroy(child.gameObject);
				}
			}
That Destroy is the culprit. If I disable it as above, the saver gets applied only once. If I enable it, twice.

What it's doing is this: I have essentially and RTS game with a pre-defined village to start with. But all buildings can be destroyed and new ones built. So instead of tracking the original buildings differently than newly built ones, I just save all buildings (original or new) and on load wipe out the village and put all buildings from the save.

This actually works well. Except for it all happening twice. :-)

Buildings have their own savers to save their internal state. So this deleting them inside here is apparently throwing things off.
NotVeryProfessional
Posts: 145
Joined: Mon Nov 23, 2020 6:35 am

Re: Save System: Custom saver applied twice for no apparent reason

Post by NotVeryProfessional »

Yes, it's the list.

if I insert

Code: Select all

	        List<Saver> copied_savers = new List<Saver>(m_savers);
at about line 670 in SaveSystem.cs and then operate on that, everything works.

So the problem indeed is that it doesn't handle the list being modified properly. Is there a reason I don't see against iterating over a copy of the savers list?
User avatar
Tony Li
Posts: 21981
Joined: Thu Jul 18, 2013 1:27 pm

Re: Save System: Custom saver applied twice for no apparent reason

Post by Tony Li »

Okay, you can count SaveSystem iterating over a copy of the savers list. Currently it allows any saver to unregister itself in the ApplyData loop but not destroy+unregister other savers. I did some performance checks, and the change is basically negligible in terms of GC compared to the GC cost of Unity simply loading any scene.
NotVeryProfessional
Posts: 145
Joined: Mon Nov 23, 2020 6:35 am

Re: Save System: Custom saver applied twice for no apparent reason

Post by NotVeryProfessional »

Excellent. Thanks.

Is this going to be an option in future versions or do I have to maintain my own fork? (well, one function fork, but still) - just so I know how to deal with updates.
User avatar
Tony Li
Posts: 21981
Joined: Thu Jul 18, 2013 1:27 pm

Re: Save System: Custom saver applied twice for no apparent reason

Post by Tony Li »

It will be the default behavior of the SaveSystem script.
NotVeryProfessional
Posts: 145
Joined: Mon Nov 23, 2020 6:35 am

Re: Save System: Custom saver applied twice for no apparent reason

Post by NotVeryProfessional »

Brilliant, as always. Dialogue System is an asset I'm always happy to use, and your relation to your customers is something that large companies could learn from.
User avatar
Tony Li
Posts: 21981
Joined: Thu Jul 18, 2013 1:27 pm

Re: Save System: Custom saver applied twice for no apparent reason

Post by Tony Li »

Thank you! :-)
Post Reply