I've just found a bug with AC's saving system:
(1) I have lots of component variable attached to the player prefab. To make this simple, let's assume it's just a simple integer though, like "NPC1 location".
(2) The scene has an actionlist that is assigned both to OnStart and OnLoad. This actionlist runs several actions to set up the scene and, before fading the camera in, it runs an actionlist asset called "NPC1 position".
(3) The "NPC1 position" actionlist checks for the "NPC1 location" integer. If it is 1, it teleports NPC1 to marker1. If the check returns false, it teleports NPC1 to marker0.
During normal gameplay, once the "NPC1 location" integer has been changed to 1, NPC1 is always found at marker1 when the player enters the scene. Also, if the player saves the game in the scene, goes to a different scene, and then loads that save, NPC1 will still be found at the correct location.
HOWEVER:
If the player quits the game and loads that save from the main menu (where that player prefab is not present) -- or if during gameplay the "NPC1 location" integer has been changed back to 0 -- the bug happens. On load, NPC1 will be sent to marker0 even if the component variable in the save says that "NPC1 location" == 1.
In other words, if the current scene either doesn't have the component variable, or if it does have it but the value is different from the one in the save, the check will return false and NPC1 will be teleported to the wrong location.
To make sure this was indeed happening, I enabled "Toggle breakpoint" on the teleport action that takes NPC1 to marker0. After loading, with the game paused because of the breakpoint, I found that:
(1) All the Global Variables have already been loaded correctly from the save.
(2) The player prefab is present in the scene, but the "NPC1 location" component variable is set to 0.
(3) NPC1 is at marker0.
As soon as I unpause the game, the "NPC1 location" component variable changes to the value in the save: 1.
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
Thanks for the details.
Issues related to this were addressed in v1.77.2. Can you confirm this is occuring in this release?
Is the Player prefab being spawned in by Addressables, and/or AC's "Player-switching" feature?
I was using v1.77.1 (I didn't realise .2 was out), but I've just updated, and I'm afraid the issue is still there.
(As a side note, thanks for the destinationThresholdOverride in PlayerMovement! But I think it needs to be a public float rather than protected? I've made the change locally and now I can use the override without issues via script.)
But I do use the Player-switching feature. The player set as default is "Player (main menu)", and we switch it to "Player (gameplay)" when the player clicks the "Start" button on the main menu.
So it's easier to test the game in the editor from different scenes, every scene's OnStart/OnLoad cutscene (except for the main menu scene) has an action that switches the player to "Player (gameplay)" right at the beginning of the cutscene. But the issue I'm reporting happens even when I remove that action from the OnStart cutscene and rely only on the character change that happens when the player clicks "Start" on the main menu. Meaning, if I remove that action from the OnStart cutscenes, use the switch player action only once, play the game as normal, and then load a save with a different "NPC1 location" value, the value from the save will still lag to be loaded.
I've tried playing around with a "Wait" action in the beginning of the OnStart/OnLoad cutscene. Started out with a 0.1s wait, which didn't work, and NPC1 only started being teleported to the correct marker when I increased the wait to 0.7s (0.6 still breaks). So it's not just a frame or two: the component variable load is lagging by a considerable amount of time, and I don't know if it's always the same amount or if this depends on the machine's performance. [Edit: It's just worked with a 0.6s wait when I tried again, so it does appear to depend on machine performance]
I'm having trouble recreating the issue.
Are you using Addressables to spawn the Player in? If not, I'd appreciate you PMing me a repro package to test with.
Use the DestinationThreshold property, which is public.
Duh, thanks! I'd typed "KickStarter.playerMovement.D" and Visual Studio didn't autocomplete it, and instead of assuming it was bugging out, I went looking for a problem that didn't exist. Now it works, sorry!
I'm not. I've DM'd you a repro project.
Thanks.
Open up AC's RememberVariables script and look for the line:
Immediately underneath, add:
Does that resolve it?
Hm, line 35, right? Just under
public override string SaveData ()
? Like this:It didn't resolve it. I tried it both in my main project and in the test project I sent you.
I've done some more experimenting here, and the issue really is specific to the fact that the component variable is a child of the player. The remember components in other scene objects don't have this issue. Does this have anything to do with the way LoadPersistentData and LoadPlayerData retrieve the Remember components differently? The former uses
HashSet<Remember> persistentSaveScripts = KickStarter.stateHandler.ConstantIDManager.GetPersistentButNotPlayerComponents <Remember>();
, and the latter uses a simpleRemember[] playerSaveScripts = player.gameObject.GetComponentsInChildren<Remember> ();
Actually, it probably doesn't have anything to do with those lines. I suspect this is the culprit (under Player.cs):
I'm assuming this coroutine is taking its time to run, and the OnStart/OnLoad cutscenes are given the go ahead to run before the coroutine is finished?
I should think you're quite right.
Oddly I wasn't able to recreate the issue following my change above - but it may be machine-dependent, and I can see how the culprit you point to could feasibly cause an issue.
I will continue to look into this, thanks for the feedback.