How to run a script once when a project is first loaded?

I would like to run a script to check for updates to modules that are used in a Unity project. This is currently using InitializeOnLoad as described in this question. This runs my updates when a project is loaded, but it also runs every time I make a code change. When a script has been edited, unity recompiles and runs the static constructor of the InitializeOnLoad class again. This update is too time-consuming to be performed on every compile.

Is there a way that I can detect when my project has been opened and distinguish this from a recompile?

What is the purpose of that code? Why does it need to run automatically? Can’t you just offer a menu item which the user can use to fire that update procedure? Also what exactly do you mean by “first loaded”?

  • Only one time ever
  • Only once per Unity editor session
  • Only once per level loaded

What you can do is creating a ScriptableObject. It is serialized so it can be found again with FindObjectOfType. However when you restart Unity it will be gone since we don’t store it as asset.

I’ve created a simple test class:

#if UNITY_EDITOR

using UnityEngine;
using UnityEditor;
[InitializeOnLoad]
public class AutoEditorCode : ScriptableObject
{
    static AutoEditorCode m_Instance = null;
    static AutoEditorCode()
    {
        EditorApplication.update += OnInit;
    }
    static void OnInit()
    {
        EditorApplication.update -= OnInit;
        m_Instance = FindObjectOfType<AutoEditorCode>();
        if (m_Instance == null)
        {
            m_Instance = CreateInstance<AutoEditorCode>();

            // your code here

        }
    }
}
#endif

I’ve created it as runtime class but wrapped it in preprocessor tags.

This should fire the code at // your code here only once per editor session.

Though i would still recommend to not perform any such time consuming task automatically.

My script is associated with an EditorWindow. Thus, I found I could declare a public bool IsInitialized; or [SerializeField] private bool IsInitialized; in my class. The value of the field is serialized, so I can use this to remember that I have already been initialized and skip it the next time. This solves the problem for my case, although it isn’t a general solution if you have something like this that you want to do outside of an editor window. Thanks for the idea about serialization, @Bunny83.