Variables set during OnPostProcessAllAssets inside containing class are reset by the time the DidReloadCallbacks callback is reached.
Hey Everyone!
I've been having some headaches with Unity recently, mainly in related to changing player defines based on the importing/removing of components from the project. I've narrowed my issue down to where I'm setting static members to be a certain value in the OnPostprocessAllAssets() function, but then when that script reaches the function called by the [UnityEditor.Callbacks.DidReloadScripts] function, that varliable has been reset.
For some very basic code examples:
public class MyClass : AssetPostprocessor
{
static mybool = false;
static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
//this is always called before OnScriptsReloaded()
mybool = true;
}
[UnityEditor.Callbacks.DidReloadScripts]
static void OnScriptsReloaded()
{
if(myBool) {
//this code is never reached, myBool always is false here
}
}
}
If anyone has any insight here on what I'm doing wrong, I'd love to hear it! Ideally, the myBool var will maintain its value across both functions.
Answer by Adam-Mechtley · Dec 11, 2016 at 02:00 PM
Hi @massivebacon! The problem is that static variables will be reset when the domain reloads. The only fields that survive a domain reload are serialized/serializable fields on a UnityEngine.Object. (See this page in the documentation.)
In this case I would recommend using something like SessionState.GetBool () and SessionState.SetBool (). I just realized these are unfortunately not documented, so I will try to get that fixed, but they basically let you store a key-value pair that exists as long as your editor session is active
Ah thanks for this. I'm assu$$anonymous$$g then you couldn't set the bool to be serializable? I believe I tried that method and it didn't work either, but wanted to check to make sure. When you have updates on the documentation for SessionState, I'd love to see it! Thanks for helping out.
Also, is OnPostProcess called on a different thread? I run into errors when trying to change a Player define in OnScriptsReloaded (to reflect the inclusion of a predeter$$anonymous$$ed class) that references an assembly/class that was supposedly imported in OnPostProcess — $$anonymous$$y script affected by the define change throws an error and says the (imported) class cannot be found, despite it just being imported. If you've got any tips generally here as well that would be great. Right now I'm pound-defining out the whole class until the class it depends on is imported, but I feel like there must be a better option.
Per the page in the docs that I linked, static fields are not serialized and cannot survive a domain reload.
In general, API points on UnityEngine.Object classes are not thread safe, so you'll find few things that happen off the main thread and they tend to be documented when it's the case (e.g., field initializers, ISerializationCallbackReceiver).
I'm not 100% sure what you're trying to do, but it's possible you may find this free package of $$anonymous$$e helpful. Specifically, the UpdateProductSymbols () method in the UnityFeatureDefineSymbols.cs file. It registers scripting define symbols based on the presence or absence of certain classes. This method can be invoked from the Editor GUI but is also called in the class's initializer (the class is also marked with InitializeOnLoad).
The issue is that I'm trying to do this ambiently in the background when a new class is imported — i.e. a class is imported and the define changes. InitializeOnLoad is only called when the editor is opened or play is pressed correct?
I also tried digging into using SessionsState, but it looks like I'm unable to access it due to its protection level. This also looks verified here: https://github.com/$$anonymous$$attRix/UnityDecompiled/blob/dc5aed5251965a5045888e8e96423025e9d0a52d/UnityEditor/UnityEditor/SessionState.cs Any help here?