In my project, I’ve been using scriptable objects as global objects for things that I need to reference often such as the player, the game instance, UI manager, etc. Up until today the “OnGlobalEnable” function seemed to always fire prior to any objects in the scene having their “Start” event invoked, which I assumed was something built into the engine itself. However after doing a bit of research, I’m thinking that this might have been simply the result of a favorable race condition based on some other factors I wasn’t controlling for elsewhere (thread here for reference).
Generally speaking my use case for these global objects is as follows
I create an asset in my project that I can reference in other scripts. This eliminates the need to search the scene or otherwise perform similar logic throughout the code.
Each of the global objects I create in this manner, in it’s “OnEnable” function will create whatever gameobjects it needs to function. For example, my “Player” global object creates a “Cursor” object that can handle interacting with objects in any scene.
I’m currently finding this pattern quite useful, as it doesn’t require me to constantly update initialization logic, and generally leverages the unity editor to solve problems that would have required little bits of code to be scatted throughout the project. Does anyone know of any thing in unity that could be referenced to get around this issue without needing to create a bunch of custom initialization logic?
For reference, here is my GlobalObject class which all such objects derive from.
It might not apply directly but I was using OnEnable() recently within ScriptableObjects and ended up with a sporadic race condition reported by some users. Once I tracked it down and was able to repro the race condition, I was able to refactor a bit.
Luckily all my SOs were already listed and managed by a singleton MonoBehaviour manager class so I refactored so that the manager class now has a single static function decorated with a [RuntimeInitializeOnLoadMethod] decorator that sets itself up and iterates all the SOs it is in charge of, telling them all to spin up.
I have editor tooling to keep the master list of SOs updated, and the list of SOs is in another type of SO that the manager class loads. You can actually see the changes I speak of in my Datasacks package, but since I just did it yesterday it is still in the feature/next branch, NOT in master yet.
The work was done in commit 53419861 but it’s as trivial as my text description of it above, and so far it seems rock-solid.
I was able to get around having a manager object by leveraging a folder in my project where I can keep all global objects, but the RuntimeInitializeOnLoad method seems to do the trick! For reference, here is my new global object script.