EditorApplication.update resetting

I've set the EditorApplication callback to one of my own, and I've simply put a debug output in it, but as soon as an asset import happens, it only continues to function for a couple seconds afterwards. I subclassed the AssetPostprocessor.GetPostprocessOrder to hook it in from the start:

public class BackgroundUpdater : AssetPostprocessor
{
    private static EditorApplication.CallbackFunction s_backgroundUpdateCB = new EditorApplication.CallbackFunction(BackgroundUpdateFunc);

    public override int GetPostprocessOrder()
    {
        EditorApplication.update = s_backgroundUpdateCB;

        return base.GetPostprocessOrder();
    }

    void BackgroundUpdateFunc()
    {
        Debug.Log("running background update func: " + EditorApplication.timeSinceStartup.ToString());
    }
}

The problem I have with this is that everytime a script (any script, not even related to this one) is reimported/recompiled, either automatically or by the context menu from within Unity, My function stops outputting to the console, therefore it is ceasing to function as an update function...

Any ideas?

You may set up a static class to be constructed each time the editor starts using the “InitializeOnLoad” attribute:

[InitializeOnLoad]
public static class MyStaticInitializer 
{
  static MyStaticInitializer()
  {
    // hook up your EditorApplication callbacks here
  }
}

Word of warning, this will also be called each time a script is recompiled.

When a script is imported, all the assemblies are recompiled, which makes all scripts reload, and resets this setup. You could try adding a static constructor to your script to set up your update function, as that will be called on assembly reload.

static BackgroundUpdater()
{
     EditorApplication.update = s_backgroundUpdateCB;
}

a better place for setting up and tearing down delegates is in a matching pair of OnEnabled() / OnDisabled functions.

instead of hooking anything relating to asset importing, I suggest putting this logic in a class that extends EditorWindow. Set your delegate in its OnEnable(), and unset it in OnDisable(). As long as your window exists, it will maintain the EditorApplication.update for you. When a recompile occurs, state is lost for just a moment, but it won’t matter, because OnDisable and OnEnable will immediately be called, and things will continue as before.

Also, for safety’s sake, use += to assign a delegate rather than =.

using UnityEngine;

using UnityEditor;
using System.Collections;

//[InitializeOnLoad]
public class EditorUpdateExample : EditorWindow
{

private EditorApplication.CallbackFunction s_backgroundUpdateCB;

int executionCount = 0;
public void BackgroundUpdateFunc()
{
	executionCount++;
    Debug.Log("running background update func: " + EditorApplication.timeSinceStartup.ToString() + " " + (EditorApplication.isCompiling ? "compiling":"compiled") + " " + executionCount + " delegate: " + EditorApplication.update);
}

[ MenuItem( "Window/Background Updater" ) ]
public static void Launch()
{
    EditorWindow window = GetWindow( typeof( EditorUpdateExample ) );
    window.Show();
} 

void OnEnable() {
	Debug.Log(this + " OnEnable");
	s_backgroundUpdateCB = new EditorApplication.CallbackFunction(BackgroundUpdateFunc);
	EditorApplication.update += s_backgroundUpdateCB;
}

void OnDisable() {
	Debug.Log(this + " OnDisable");
	EditorApplication.update -= s_backgroundUpdateCB;
}

void OnProjectChange() {
	Debug.LogWarning("OnProjectChange");
}

public void OnGUI()
{
	EditorGUILayout.SelectableLabel((EditorApplication.update!=null)?EditorApplication.update.ToString():"NONE");
}

}