Force Unity to recompile scripts

Hi all,

I would like to know if it’s possible to tell Unity (in the editor) to recompile scripts (just like when you tab in/out of Unity and it checks for changes and recompiles).

The reason I am asking is because I have made an editor script which (through a menu item) makes some changes to script files. The problem is that these changes do not show up until you tab out/in of Unity to make it recompile. If I could make Unity recompile automatically that would be awesome.

Thanks for any input!

/Simon

Unity 2019.3 introduced public editor API to force scripts recompilation: it’s UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation method. Tested it with hooking to assembly compilation started/finished events and this method indeed recompiles all scripts in the project.


For Unity versions from Unity 2017.1 to Unity 2019.2 can call UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface.DirtyAllScripts via reflection. DirtyAllScripts is the method Unity 2019.3 calls internally from RequestScriptCompilation method (see reference). Sadly for Unity versions older than 2017.1 I’m not sure DirtyAllScripts is present since Unity C# reference has no source code for that Unity versions.


Simple editor window to force scripts recompilation on button click (tested with Unity 2019.3.0f6 and Unity 2017.1.1f1):

using UnityEditor;
#if UNITY_2019_3_OR_NEWER
using UnityEditor.Compilation;
#elif UNITY_2017_1_OR_NEWER
using System.Reflection;
#endif
using UnityEngine;

namespace PumpEditor
{
    public class CompilationWindow : EditorWindow
    {
        [MenuItem("Window/Pump Editor/Compilation")]
        private static void ShowWindow()
        {
            var window = EditorWindow.GetWindow<CompilationWindow>();
            window.titleContent = new GUIContent("Compilation");
            window.Show();
        }

        private void OnGUI()
        {
            if (GUILayout.Button("Request Script Compilation"))
            {
#if UNITY_2019_3_OR_NEWER
                CompilationPipeline.RequestScriptCompilation();
#elif UNITY_2017_1_OR_NEWER
                var editorAssembly = Assembly.GetAssembly(typeof(Editor));
                var editorCompilationInterfaceType = editorAssembly.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface");
                var dirtyAllScriptsMethod = editorCompilationInterfaceType.GetMethod("DirtyAllScripts", BindingFlags.Static | BindingFlags.Public);
                dirtyAllScriptsMethod.Invoke(editorCompilationInterfaceType, null);
#endif
            }
        }
    }
}

AssetDatabase.Refresh should do what you want.

AssetDatabase.ImportAsset will allow you to update only a specific asset.

I know this question is years out of date, but I’ve just run into a situation where AssetDatabase.Refresh() and AssetDatabase.ImportAsset() don’t seem to cause a recompile.

I’m using some editor scripts to keep multiple copies of several of the .asset files in the ProjectSettingsFolder - this allows me to have multiple build configurations set up with different scripting defines, different scenes, etc.

Each build configuration has its own copies of the .asset files stored in a folder and I copy them over the ones in the main ProjectSettings folder to change build configuration.

Normally if you edit the scripting defines in the player settings inspector this triggers a recompile, but this doesn’t seem to happen if you copy a new ProjectSettings.asset file over the main one from script.

AssetDatabase.Refresh() and ImportAsset() also didn’t seem to help.

Whilst messing about with some other editor code recently I noticed that when a script execution order is changed this forces a recompile of all scripts, so I’m using this snippet of code to force a recompile of all scripts after I change the settings file and it seems to work reliably (N.B. this will only work in editor code)

MonoScript cMonoScript = MonoImporter.GetAllRuntimeMonoScripts()[ 0 ];
MonoImporter.SetExecutionOrder( cMonoScript, MonoImporter.GetExecutionOrder( cMonoScript ) );

As you can see it makes a change that doesn’t change anything, but this seems to trigger a complete recompile of all scripts :slight_smile:

Hope this helps someone :slight_smile:


Update (November 2016):

Apparently MonoImporter is now undocumented so this technique may stop working soon.

Another way to force a recompile manually is to change the scripting define symbols (in the player settings window) to a new value.

It is possible to set this from script using PlayerSettings.SetScriptingDefineSymbolsForGroup() and one of the plugins I bought off the asset store seems to use this method to force a recompile but I’ve yet to need to try it so I can’t offer sourcecode.

The one thing to mention to anyone thinking of trying this is that I would assume the editor only triggers a recompile if the symbols you pass are different to the ones already set…


Update (June 2018):
The MonoImporter method no longer seems to work.

I’m now using PlayerSettings.SetScriptingDefineSymbolsForGroup() as mentioned above.

The code I have adds a dummy symbol to the end of the symbols which has a number in it - e.g. “_dummy_0”.

Each time I need to force it again I parse the symbol string to find the number on the end, remove the existing symbol and add a new one with a number one higher (which wraps back to 0 eventually).

FWIW you could just use 2 different unique symbols and swap which you use each time which would be simpler but I’ve written the code now :wink:

Have you tried Clicking Assets->Refresh Assets(or ctrl+r in windows cmd+r on mac)?

The script(s)/class(es) should reload automagically as long as you actually saved them in your editor of choice, at least that has been my experience.

This is an implementation of @darbotron answer. @darbotron did the findings and idea in his update from June 2018. Tested working in Unity 2018.2.0

public static void ForceRebuild()
{
    string[] rebuildSymbols = { "RebuildToggle1", "RebuildToggle2" };
    string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(
        EditorUserBuildSettings.selectedBuildTargetGroup);

    if (definesString.Contains(rebuildSymbols[0]))
    {
        definesString = definesString.Replace(rebuildSymbols[0], rebuildSymbols[1]);
    }
    else if (definesString.Contains(rebuildSymbols[1]))
    {
        definesString = definesString.Replace(rebuildSymbols[1], rebuildSymbols[0]);
    }
    else
    {
        definesString += ";" + rebuildSymbols[0];
    }

    PlayerSettings.SetScriptingDefineSymbolsForGroup(
        EditorUserBuildSettings.selectedBuildTargetGroup,
        definesString);
}

Just create some .cs file in the asset folder and rename it to some random value. Then call AssetDatabase.Refresh();
This makes scripts recompiles

EditorUtility.RequestScriptReload()

Hi there! I made a utility script that allow us to force recompile code, without tweaking any file:

using UnityEngine;
using UnityEditor;

public class Recompiler : ScriptableObject
{
    public static void Recompile()
    {
        // Create a temporary instance of Recompiler
        ScriptableObject tmpInstance = CreateInstance<Recompiler>();
        // Get the script asset that Recompiler object uses
        MonoScript sourceScriptAsset = MonoScript.FromScriptableObject(tmpInstance);
        // Get the script asset path
        string scriptPath = AssetDatabase.GetAssetPath(sourceScriptAsset);
        // Call DestroyImmediate() in order to destroy the temporary instance properly
        DestroyImmediate(tmpInstance);
        // Reimport the script asset, at the computed path
        AssetDatabase.ImportAsset(scriptPath, ImportAssetOptions.ForceUpdate);
    }
}

Add this script in an /Editordirectory of your project, and call Recompiler.Recompile() where you need to force Unity to recompile scripts.

I don’t know if the EditorUtility.RequestScriptReload() suggested by @Raresh works, but it exists only in Unity 2019, and I’m working on a project that uses Unity 2018. So this little utility script did the job! :wink: