Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to trigger the rebuild of scripts from the editor?

Discussion in 'Scripting' started by DanVioletSagmiller, Mar 14, 2022.

  1. DanVioletSagmiller

    DanVioletSagmiller

    Joined:
    Aug 26, 2010
    Posts:
    203
    I'm using an editor script to change the Build define statements, with this code:

    Code (CSharp):
    1.         UnityEditor.PlayerSettings.SetScriptingDefineSymbolsForGroup(
    2.             targetGroup: UnityEditor.BuildTargetGroup.Android,
    3.             defines: "SERVER_MODE;DEVELOPMENT_BUILD;UNITY_POST_PROCESSING_STACK_V2");
    Next, to get Visual Studio to update its changes right away, I execute this line:

    Code (CSharp):
    1. Unity.CodeEditor.CodeEditor.CurrentEditor.SyncAll();
    At this point, there is a menu option I want to show up only with SERVER_MODE defined.

    Code (CSharp):
    1. #if SERVER_MODE
    2.     [MenuItem("Tools/Set To Normal")]
    3.     public static void SetToNormal()
    4.     {
    5.         ...
    6.     }
    7. #endif //SERVER_MODE
    The PROBLEM is that the menu option does not come up on its own. As soon as I click away and then back into Unity, it figures out a recompile is in order and then runs it. But I cannot get it to do this on its own. If I just sit there for a minute, nothing happens, the menu option will not show up.

    I have tried
    Code (CSharp):
    1. UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation();
    2. AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    3. AssetDatabase.ImportAsset("Assembly-CSharp.csproj", ImportAssetOptions.ForceUpdate);
    4. AssetDatabase.ImportAsset("Assets/!/Scripts/Editor/EditorProgressBar.cs", ImportAssetOptions.ForceUpdate);
    5.  
    6. // or even any of those from within UnityEditor.Compilation.CompilationPipeline.assemblyCompilationFinished
    7.  
    No matter what, I cannot get this to rebuild the code. It could be a timing issue, but I assumed running the refresh attempts from within "UnityEditor.Compilation.CompilationPipeline.assemblyCompilationFinished" should have worked in that case.

    Any thoughts?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    You should be able to just call
    AssetDatabase.Refresh();


    Caveat: that's what I use to recompile generated code. I have not tried it after only changing a script define but I imagine it should detect that change too.

    EDIT: you might also need to call one or both of these before refresh:

    Code (csharp):
    1. EditorUtility.SetDirty(WhateverItWasThatYouChangedDefinesWith);
    2. AssetDatabase.SaveAssets();
     
  3. DanVioletSagmiller

    DanVioletSagmiller

    Joined:
    Aug 26, 2010
    Posts:
    203
    AssetDatabase.Refresh(); hasn’t worked, but your comment about generated code made me realize that the defines are in the csproj file, but that is not an asset. Deleting and regenerating a test cs file would probably do it. Perhaps if I find and wipe out the main dll file…
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    Hm, doesn't matter what Visual Studio compiles from that csproj file. Unity certainly doesn't use it.

    Unity is the compiler that actually matters and it will use what those Player Settings defines are whether they make it out to the csproj or not.
     
  5. DanVioletSagmiller

    DanVioletSagmiller

    Joined:
    Aug 26, 2010
    Posts:
    203
    I don't know a way to set a script file as dirty. I.e. the SetDirty function only works with a Unity Object, not a path to a script file.

    I agree, but changing the define fields does not appear to trigger a recompile. by the nature of what is being done, this absolutely should trigger recompile. But it does not, until Unity loses focus and gets it back, or some other event triggers the recompile. :( At least not in Unity 2020.3.30f1.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    Sigh. Ah well.

    Your idea here:

    That might be the lowest friction... but you'd want to ignore that file in source control because it would have to change something in the file each time: an identical file , even touched, will not be recompiled.

    Again, sigh.

    That's interesting... I approve of that but not sure how cross-platform it would be.
     
  7. DanVioletSagmiller

    DanVioletSagmiller

    Joined:
    Aug 26, 2010
    Posts:
    203
    Got it. It is triggering it, but it is seriously delayed, on a very small project, The recompile is happening, but it doesn't start for 5-10 seconds. It operates successfully from just the "SetScriptingDefineSymbolsForGroup" command called out above. It is just inobvious and slow. I would much rather freeze the UI with a dialog while this change happens. Or find a way to speed it up.
     
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    Again, sigh. :)

    There are some fairly new settings (preferences?) related to domain reload... I'd tell you exactly where they are but I'm not on a machine with a modern version of Unity right now. Just goog for domain reload in Unity, maybe one of those settings can help that delay.
     
  9. ShawnFeatherly

    ShawnFeatherly

    Joined:
    Feb 22, 2013
    Posts:
    57
    I've forced a recompile with a hacky method. If you're open to hacky...oddly enough, it leverages putting dummy data into the `SetScriptingDefineSymbolsForGroup` you're already using. My example of it and some others suggestions are at http://answers.unity.com/answers/1590935/view.html

    Here's a copy of the code posted there:
    Code (CSharp):
    1. public static void ForceRebuild()
    2. {
    3.      string[] rebuildSymbols = { "RebuildToggle1", "RebuildToggle2" };
    4.      string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(
    5.          EditorUserBuildSettings.selectedBuildTargetGroup);
    6.      if (definesString.Contains(rebuildSymbols[0]))
    7.      {
    8.          definesString = definesString.Replace(rebuildSymbols[0], rebuildSymbols[1]);
    9.      }
    10.      else if (definesString.Contains(rebuildSymbols[1]))
    11.      {
    12.          definesString = definesString.Replace(rebuildSymbols[1], rebuildSymbols[0]);
    13.      }
    14.      else
    15.      {
    16.          definesString += ";" + rebuildSymbols[0];
    17.      }
    18.      PlayerSettings.SetScriptingDefineSymbolsForGroup(
    19.          EditorUserBuildSettings.selectedBuildTargetGroup,
    20.          definesString);
    21. }
     
    Last edited: Mar 15, 2022
    Kurt-Dekker likes this.
  10. DanVioletSagmiller

    DanVioletSagmiller

    Joined:
    Aug 26, 2010
    Posts:
    203
    Thanks. I did try that. It does automatically make the changes, but it can still take up to 5 to 10 seconds with the editor fully available to make additional changes, before these ones take effect. Unity is still delaying that change (Unity 2020.3.31.f1) This means that I can't trust it happened until I become aware Unity has refreshed. :( The solution so far appears to be that we must allow the wait, and that there is no good solution. perhaps triggering a System SendKeys event for windows, of Alt+Tab, then Alt+Tab to switch off and back into the Unity app would work better. I.e. if I manually click away and back in, it updates instantly.
     
  11. Apollo-Meijer

    Apollo-Meijer

    Joined:
    Mar 30, 2015
    Posts:
    31
    Hey! Do you know in what version of unity this is now fixed?