Messing up references when regenerating prefabs

Discussion and help for Easy Save 3
RequiemOfTheSun
Posts: 14
Joined: Tue Dec 29, 2020 4:14 am

Re: Messing up references when regenerating prefabs

Post by RequiemOfTheSun »

I've had the checkbox checked.

What I was seeing that steered me this direction was in ES3Prefab ApplyReferences the if(localToGlobal.TryGetValue) bit was never returning true for my world objects. I noticed these localRefs are built when running the game and figured maybe my scene changing was causing issues. I use a script that uses RuntimeINnitializeOnLoadMethod to run BeforeSceneLoad and swap scenes to my main menu scene. Not sure if that's part of the problem. I'll test on my test scene.

I still have an issue where if I modify my prefabs those local refs break and I can't load by ref the parent relationship of children that were nested under children within the prefab anymore.
RequiemOfTheSun
Posts: 14
Joined: Tue Dec 29, 2020 4:14 am

Re: Messing up references when regenerating prefabs

Post by RequiemOfTheSun »

Oh I'm also not saving children of these prefab objects. I'm not sure if that's part of my modified prefab problem but it seems like a waste to save out the entire contents if I don't need to.
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Messing up references when regenerating prefabs

Post by Joel »

RequiemOfTheSun wrote: Tue Jan 19, 2021 6:53 pmI still have an issue where if I modify my prefabs those local refs break and I can't load by ref the parent relationship of children that were nested under children within the prefab anymore.
If you're able to private message me a new project with a basic scene which replicates this I'm happy to look into it.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Messing up references when regenerating prefabs

Post by Joel »

Thanks for sending that over, much appreciated.

The issue is because you're destroying the parent before loading. Because this object exists in the scene prior to runtime, it is not a prefab instance. Therefore a reference with that ID will still exist in the reference manager with the value of null. This is expected behaviour as in most cases it is desirable for this to happen.

If you don't want this to happen, you will need to remove the references from the reference manager after destroying your objects. You can do this by calling ES3ReferenceMgr.Current.RemoveNullOrInvalidValues() after destroying the objects. I.e.

Code: Select all

foreach(Transform child in solarSystem.transform)
    DestroyImmediate(child.gameObject);
ES3ReferenceMgr.Current.RemoveNullOrInvalidValues();
All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
RequiemOfTheSun
Posts: 14
Joined: Tue Dec 29, 2020 4:14 am

Re: Messing up references when regenerating prefabs

Post by RequiemOfTheSun »

Hi Joel, thanks for taking a look.

Were you able to repro that your suggested solution fixes my issue here? I'm still reproducing my prefab modification issues even while removing nulls and invalids from the reference manager.

The method I'm using is ES3ReferenceMgr.Current.RemoveNullValues() as of the latest ES3 update, is this correct? I've PMed you another copy of my project with your suggestion and with the slight change that I'm now always instantiating the world from a prefab during Start instead of initially being a world object.

Thanks for the help, your support is very valuable and I hope I can get a handle on this issue as it'll pretty much handle all the complexity I can throw at it if I can just figure out what's going on here and how I might get my ideas working.
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Messing up references when regenerating prefabs

Post by Joel »

Hi there,

In our upcoming update we actually account for recently destroyed objects when accessing the reference manager, and this appears to resolve your issue. If you private message me your invoice number I'll send this over ahead of it going live on the Asset Store.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
RequiemOfTheSun
Posts: 14
Joined: Tue Dec 29, 2020 4:14 am

Re: Messing up references when regenerating prefabs

Post by RequiemOfTheSun »

I have figured out where things are breaking. It is a defect and I think with some tiny changes you'll be able to get this working for me and anyone affected in the future. I'm working with a slightly modified version of your stuff now and it's fixed my remaining issues related to modified prefabs breaking existing saves.

Your suggestion to enable 'save GameObject children' bloated my save files and caused significant slowdown when saving and loading. Since I've refactored my project to depend entirely on instantiating 'ES3Prefab's I don't think I need to go that far. You do after all have the 'localRefs' and the 'localToGlobal' concepts in your 'ES3Prefab' code that should work perfectly for me.

So I went down the rabbit hole and read through a big chunk of your code (brilliant stuff btw, this tool is great) and I ended up with some cool improvements, or so I thought. Instead I realized that what I did and what you did with 'localToGlobal' and 'localRefs' were relying on the same underlying concepts, so I asked myself why your stuff was broken while my stuff was working. I think I've figured it out and I can save the next guy from scratching their head on this bug for as long as I have.

Right now you call 'ES3Prefab.GeneratePrefabReferences' against every prefab every time you call 'ES3ReferenceMgr.RefreshDependencies'. This updates the 'ES3Prefab.localRefs' but only on the version of the prefab in the Assets folder on the Project pane. What it does not do is update the localRefs on the actual prefab itself. You can verify this by looking in the Inspector at the 'Reference count' on the 'ES3Prefab' component. When checking the 'Reference count' from inside the prefab editor I initially see a count of '0' for a newly added component. Then I start the scene which updates the 'localRefs' through the 'ES3ReferenceMgr'. At this point I can go to the Asset on the Project pane and see the 'Reference count' has gone up. However opening the prefab editor again the 'Reference count' is still 0.

I believe this is the source of the bug and here's why I think it happens, when you modify a prefab through the prefab editor Unity seems to reset the instance of the prefab that appears in the Assets folder on the Project pane. The Asset version gets a new copy of the 'ES3Prefab' from the version of the prefab you see in the prefab editor which as described above is missing the 'localRefs'. When 'ES3Prefab.GeneratePrefabReferences' is next called it regenerates the 'localRefs'. Now all existing save files are broken because their 'localToGlobal' referenced the previous 'localRefs'.

My recommendations:
1) Find a more reliable place to call 'ES3Prefab.GeneratePrefabReferences'. I'm using a callback to 'PrefabStage.prefabSaving' setup during 'OnEnable' in the 'ES3PrefabEditor'. The issue with this is I don't get a callback when I add or remove components from the root of the prefab without opening the prefab editor. However it works great for other editing. One benefit is you can see the references update as you modify the Prefab which takes some of the guess work out of if the 'localRefs' have the expected changes.

2) Expand the 'localRefs' in the 'ES3PrefabEditor' and make them editable like the dictionary in your reference manager. This lets someone manually recover local ids if they get accidently changed and is useful for verifying this bug is fixed.
2a) I've added a 'Refresh' button here as well. It comes in handy because my solution for recommendation 1 isn't perfect.
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Messing up references when regenerating prefabs

Post by Joel »

Hi there,

Just an update that I'm not ignoring your message. As there's quite a lot to look into here this will take a bit of time :)

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
RequiemOfTheSun
Posts: 14
Joined: Tue Dec 29, 2020 4:14 am

Re: Messing up references when regenerating prefabs

Post by RequiemOfTheSun »

Take your time, no reason to rush as I'm working great with the recommendations I made. Took me 3 months to find the time to sit down and really dig into ES3 for a weekend so I get it.

This fix should help anyone who like me loves ES3 but would rather drive the save/load code manually through the use of prefabs than accept the downsides of the AutoSaver. I just search the scene for ES3Prefabs, save them and when it comes time to load, everything works like a dream. Smaller save files and more useful too since I can do whatever I want to my prefabs so long as I keep the saved references around.
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Messing up references when regenerating prefabs

Post by Joel »

Thanks for your patience. Some more digging has unearthed the underlying problem.

There's a bug at Unity's end where it will fail to deserialize data when using their ISerializationCallbackReceiver event when Prefab Edit mode is open. This means that instead of returning the serialised data, it returns null, wiping the localRefs and any reference IDs which were there.

The workaround for this is quite simple: we simply ignore Unity when it fails to deserialize data. I'll also see about putting together a bug report for Unity when I get a chance.

In the meantime I'll PM you this update. I've also made the localRefs accessible from the Editor.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Post Reply