How to ensure singletons are initialized in Edit Mode
I'm creating a level editor where I want to save objects from the scene to a level asset, and the other way around - instantiate objects in the scene using data from the level asset.
My problem is when I go to load a level, I need certain singleton instances to be there to instantiate the objects, and I'm seeing strange behavior where sometimes the instance is there, and sometimes it is null.
Here is my setup:
LevelEditor class extends the Editor for my custom level asset. Has buttons for save/load to scene. On load click, I call a static method in 3 singleton managers to create the objects I need and add to hierarchy.
These static Create methods rely on properties in the singleton instance of the manager class. For example, I need to reference prefabs and assets in public variables of the singleton manager. Same Create methods work in Play Mode.
This process is failing when the singleton instance is null. For some reason, this is not always the case, and I have no idea why. When the instance happens to be there, it works and the objects are created to the scene on the Editor button click, same as in play mode.
I have already tried:
Adding [ExecuteInEditMode] to the singleton manager classes.
Putting the singleton manager classes at the top of the ScriptExecutionOrder, and prior to the class used to call the static Create methods.
[Edit]: Just discovered an important clue I think. Every time I rebuild code, that's when it breaks - singleton instances are null again. Then when I run in play mode, all those managers are initialized. And since the are using [ExecuteInEditMode], they stay initialized for the Editor. When I next click the load asset button, now the singleton instances are already created.
So how can I force them to initialize from the editor without entering play mode?
Answer by halken · Sep 26, 2017 at 05:37 AM
Ok, for anyone finding this later, I came up with a solution. Amazingly simple! I just check if the instance is null, and then set the instance to the manager I have in the hierarchy.
Now, anywhere the EditorScript needs to reference instance variables of my singletons, I first check if the instance is null, and then set it to the manager object I have in my scene hierarchy. So the instance is normally set in Awake. But every time I rebuild the code, Unity will lose the link to those instantiated singletons. After I set it manually, I can use all the data I have configured into the manager within the scene. This solution is much better than others I've found where you manually recreate the manager from scratch - that would leave all those variables reset to null.
Make sure [ExecuteInEditMode] is defined on the class - doesn't work without this. Example:
// Before referencing any instance variables, use the controller in the hierarchy if this is called from Editor Scripts and doesn't have an instance yet.
if (instance == null)
{
instance = GameObject.FindObjectOfType<BrickController>();
}
brick = Instantiate(instance.brickPrefab, position, Quaternion.identity, instance.hierarchyParent.transform);
I am having this exact problem, but I can't figure out where/how to implement the solution you posted here to fix my problem. How do I use that code to solve the problem?
So this was a while back, but I think in my case, I was trying to reference variables stored in a singleton class, which exists as a script in a heirarchy object. For example this BrickController. In my case, I wanted to instantiate a brick using a prefab variable from that singleton.
So in my editor code (like on button click), I was finding that the singleton object I needed was sometimes null (that would be the "instance" variable in example above, of type BrickController). To fix this, wherever you are about to reference the singleton, first check if it is null, and if so, assign it to the only one that exists in the hierarchy using a FindObjectOfType() call. After that, you can assume you have a reference to your singleton, regardless of the state of the editor loading these hierarchy objects.
Your answer
Follow this Question
Related Questions
ExecuteInEditMode is not working when trying to instantiate a new GameObject [SOLVED] 1 Answer
How can I in-script create gameobject from prefab? 2 Answers
Singleton / DontDestroyOnLoad / Instantiation referencing 0 Answers
Prefab Scripts Not Working After First Spawn? 2 Answers
Instantiate more than 1 prefab 0 Answers