For the core component of a framework I develop, I’m doing some magical things during deserialization. These magical things includes accessing a scriptable object which sits in Resources folder. Since the scriptable object must be load before deserialization, I tried to load it in my InitializeOnLoad method decorated with RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad) attribute.
Unfortunately Unity runs the scene deserialization before InitializeOnLoad method so I get an error during deserialization because I didn’t get a chance to load the required scriptable object first.
I tested the editor version of RuntimeInitializeOnLoadMethod attribute which is InitializeOnLoadMethod and it works well. I mean, the editor version of InitializeOnLoad method runs before any scene loading operation so my scriptable object gets loaded before scene deserialization and I don’t get an error in editor.
As soon as I begin play mode, I get the error because scene deserialization runs before RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad).
I don’t think this will be recognized as a bug and be fixed anytime soon by Unity so I’m looking for an alternative solution.
I tried adding the scriptable object to Preloaded Assets list in project settings but for some reason (maybe another bug) Unity doesn’t load it either before scene deserialization.
I may start the game with an empty scene which immediately loads the actual game scene but this is not a good alternative because 1) This would impossible to play the currently loaded scene in editor, 2) Since I’m developing a framework, I would have to ask the framework consumers to do the same trick which is extremely ugly.
Can you guys think of another way I can load this scriptable object before first scene deserialization?
For the curious kittens who wonder what kind of magic I’m doing in deserialization and why I’m doing it: It’s really not the focus of this topic.
I remember having a similar trouble. I have a number of scriptable objects used for databases that I need it to check during deserialization. I’m pretty sure it’s doable if you take to account how much the loading take (I did it many times), but every time you’d make an operation be a bit more expensive it’d give trouble.
Eventually, and for a different reason, with the appeareance of the nested prefabs I ended creating a base level prefab that I put to all my scenes. I eventaully realized that I can just can put my databases in a public variable there and be sure they’ll be in the scene since the very start. It’s super easy to update since a prefab. You can also use it for other things, I actually put there my GUI, the character and a basic scenery. It makes creating a new level super easy. Sounds a bit stupid but it’s an easy solution and opposite to other ones, it never breaks. And with it you pretty much can get rid of singletons all together and not worry about wich one loads first and that sort of annoying stuff.
@calpolican Yea, I’m thinking about something similar. I may have to force all instances of my core component to include a reference to the said scriptable object via editor code. An ugly solution but it may be the only solution. Also, I can hide that reference field so the users won’t break it manually.
jessomator11:02 AM
Then the question becomes, can you have a separate pass after Deserialization. If,say, the funky read logic happened during Awake or Start?
xtro3:25 PM
My magic needs to happen during deserialization because 1) it needs to run in edit mode too, 2) Some deserialization triggering events trigger awake in editor (e.g. Scene load) but not all (e.g. Recompile).
I could prevent my magic to run in deserialization and divert it to awake in playmode, yes but unfortunately Unity doesn’t allow me to check Application.isPlaying during deserialization either