0
Fixed

Runtime scene loading causes deserialization failure

Florian Poot 2 years ago updated by Lazlo Bonin (Lead Developer) 2 years ago 23 2 duplicates

Hello,

I have a problem that sometimes my Bolt scripts are not executed (my C# scripts are).
I am using Unity 2018.2.11f1 and Bolt 1.4.0f8


This is the log I have

output_log.txt

Thanks !

Bolt Version:
Unity Version:
Platform(s):
Scripting Backend:
.NET Version (API Compatibility Level):

Duplicates 2

Pending Review

Hi Florian! There seems to be something really weird happening here. 

Can you post the macro files for the graphs that fail to deserialize?

Are you doing anything funky in there (recursive graphs, changing the macro at runtime, etc.?)

Pending Review

Hi GhostAegis!

Sorry for the late reply on this.

In order to reproduce this, can you tell me how exactly the prefabs get instantiated "right at the start of a scene"? Is it from a Bolt graph or from a C# script? 

A simple project one macro and one prefab that reproduces the issue would be very welcome!

No worries! I'm away from my machine for a few days, but I'll be able to put something together Monday or Tuesday next week if you like.

I can describe in a little more detail though, hopefully that might be helpful in the interim:

There's a Bolt graph (which is a macro) which instantiates a number of prefabs on start before setting up some object variables on those prefabs. The prefabs are fairly complex with a number of nested levels of objects, many with their own macros, some state and some flow machines.

If I start a scene directly from the editor, everything works fine. However, if I start on say, a menu scene in the editor, and then navigate through the menu and load a scene that has the on start instantiation graph, when it loads the prefabs on start the resulting prefabs have been stripped of all of their Bolt references on every object. 

All the macros have been unassigned and reset to none and all of the object variables have been reset. Note that this only happens when instantiation happens on start. 

Now, if I leave those same prefabs in the scene as part of the scene itself (so that they are not instantiated), everything works fine. Also, any additional prefab instantiations that happen after the initial start call that happens on first scene load work just fine. No Bolt references are lost in that case.

I've not been able tor reproduce this behavior in a build so far, so it seems to be something unique to start calls that execute instantiation that happen on scene load in the editor only.

I'm not changing the macro at runtime and I have this kind of recursive graph:

.

After spending few hours on the problem I noticed that it seem to be related to the LoadScene in additive mode of my "objectpool" scene (which contains around 25 GameObjects with state machine on it). I solved the problem by adding a WaitForNextFrame unit before loading.


The bug occurs randomly and even reloading the scene is not enough we must restart the game. It happens on both Windows and Android. I think all the graphs failed to deserialize because when it's bugging nothing is working.

Here is the macro of the GameObjects in my ObjectPool and the macro that load the ObjectPool:

Vehicle.asset

GameController.asset

Thanks !

In fact, this is the same bug that I described a few months ago in

https://support.ludiq.io/communities/5/topics/1937-on-button-click-not-triggered-in-build-bolt-14-beta-2

and it was solved by the same solution as above

Ah, interesting. It seems like some Live Editing handlers fail because machines are being created while they are iterating on the existing set of machines. This is a tricky issue, I'll have to have a close look at your test case to fix it without breaking anything else. Thanks for the report!

Pending Review

Hi GhostAegis!

Thanks for the report. I'm merging yours with a similar issue that was reported last week. This seems critical and will be my top fix priority. 

So after a little testing it seems like this issue is related to this one here: https://support.ludiq.io/communities/5/topics/2258-runtime-instantiation-causes-deserialization-failure. Weirdly, I cannot reproduce the issue where it happens in the editor outside of this one case. That's only happening in this one case for some reason. Otherwise it does seem limited to builds.

Edit: Okay, definitely related. I switched the instantiate calls that were causing the problem from a Start block to the first frame of Update and the problems vanish.

Cannot Reproduce

Hi everyone,

I can't reproduce this so I need your help isolating a minimal project that triggers the error.

Here's my attempt:

  • Scene 2258, which contains a sphere that loads scene 2258a when you click it.
    It also contains a cylinder with a macro called 2258m which logs the object name on start.
  • Scene 2258a, which has a single cube with the 2258m macro too.
  • Loading 2258a by clicking the sphere in 2258 does not cause any error.

Linking my small test files here, please edit them until you can recreate the error!

2258.zip

+1

Hmm, okay, I'll do my best. I was definitely having trouble replicating the behavior in a stripped-down project as well. 

If I can't get it to work in the minimal project, then this weekend I should have time to do a step-by-step strip-down of one of the scenes in my projects where I'm seeing the behavior and get it reduced to a point where it's still causing the problem but also shareable.

Thanks! Yep, it's a pain, but a small reproducible project is the only way we can truly isolate an issue & test if we really fix it.

Ok, so I succeed to reproduce the bug in a small project ! (Actually it's my big project from which I deleted all the useless files)

Here is the project: https://drive.google.com/file/d/1Ivz-VKsbDiWEJWHpEaAbFjbuXbRA5DVg/view?usp=sharing

The bug does not happen every time and not on every device (I don't know why)

So here are my specifications which bug occurs almost all the time (it's a Yoga Book from Lenovo):

Intel Atom processor x5-Z8550 @ 1.44Ghz
4 GB of RAM
Intel HD Graphics

But it does'nt seem related to the performance of the device because on my Android phone, which is a Motorola G4 Play, with a Snapdragon 410 and 2 GB of RAM, this never happens (It happen on others Android phone).

Try changing resolution or graphics quality if everythings works fine.


Hi Florian! Thanks for making a minimal project, however I still can't reproduce it with the files you linked. In theory it shouldn't be related to resolution, graphics quality or performance though.

So I haven't been able to reproduce it, but I'll be issuing a tentative fix for v.1.4.0f10.

Basically, what seems to happen is that objects are Awake-ing while other objects are getting deserialized. I'm guessing it may have to do with a quirk in Unity multithreading mentioned here:

Beware that the serializer, including these callbacks coming from the serializer, usually do not run on the main thread, so you are very limited in what you can do in terms of invoking Unity API. (Serialization happening as part of loading a scene happens on a loading thread. Serialization happening as part of you invoking Instantiate() from script happens on the main thread).

My fix will attempt to put a mutex on the machines collection to make sure the loading thread doesn't modify it while it's being iterated upon. If all goes well, it should be enough. If there's an unexpected side effect, you might get a deadlock, meaning your game will freeze completely instead of outputting the deserialization failure error you posted.

You'll have to let me know how it goes!

Another note re: loading scenes: it's normal that you have to wait one frame before a scene is loaded. This is by design in Unity. Here's an answer from a UT staff on the forum that confirms it:

The way scene loading work and always have worked in Unity is that it complete in the next frame (Async version maybe even later), so you cannot immediately change the active scene to the new scene it simply not loaded at that point.

The right solution is coroutines or some other way of waiting at least one frame for the loading to complete. LoadScene is guaranteed fo complete in the next frame, LoadSceneAsync has no guarantees about completion time.

So I can't seem to get the hotfix installed. Any attempt to import it shows all files with the "Files exist, but with different GUID. File will be overwritten, which may be undesired." warning. 

If I actually proceed and let it install anyway, I end up in a state where Bolt thinks it's been installed fresh and pops up the setup wizard instead of the update one. However, any attempt to use the setup wizard in that case fails, though after a few attempts and reversions, never at the same place twice.

Any ideas on what's happening?

The GUID change should be a harmless warning that's a consequence of preparing our codebase for Bolt 2. It may cause the setup wizard to show up again, but in this case, yes, just go through it.

If you have failures during the setup wizard, please start a new thread with the errors and reproduction steps!

Got it! Okay I'll try again and see if I can get it through. If not I'll make a new thread.

Bolt 2 looks incredible, by the way. Just saw the blog post. Can't wait!

Update: That did the trick. Thank you!

Oh man I'm glad someone else narrowed it down. I could not for the life of me isolate it from my game scenes and it was driving me absolutely crazy. 

But yeah, now that I actually see it written out, delaying instantiation until after everything is loaded and ready to go does make a lot of sense. I'll integrate the hotfix and see if that sorts it for me as well and report back.

+1

Hey, it looks like the bug is fixed. Thanks a lot ! Anyway it's a good idea to put a WaitForNextFrame unit so we're sure the scene is loaded as you said above.

It's a multithreading issue, so yes, it is almost impossible to isolate and reproduce every time. It depends on the computer and the context. Glad to hear it's fixed for you!