How can I change Scripting Define Symbols before a command line batchMode executeMethod?

I am using batchMode to make my builds automatically and in my build scripts I programmatically change the Scripting Define Symbols using the PlayerSettings.SetScriptingDefineSymbolsForGroup method to turn on/off flags that are required for specific build types.

The problem is that some of my code does not compile unless PlayerSettings.SetScriptingDefineSymbolsForGroup has changed #if DEFINES before running my build scripts. This makes my build fail because the project does not compile and it cannot change the Scripting Define Symbols. The only way I can work around this is by committing a ProjectSettings/ProjectSettings.asset with the proper defines so my project compiles before the build starts.

This is not a useful workaround though because it adds manual steps to builds that should be automatic.

The only other way I can think of is doing a search and replace inside the ProjectSettings.asset of all of the Scripting Define Symbols I need to change but judging by how it looks, it might be a bit error-prone to do this with a script. Here is what it looks like inside:

  scriptingDefineSymbols:
    1: RR_DEV
    2: RR_DEV
    4: NOT_COMPILING_DEFINE
    7: 
    11: RR_DEV
    14: UIRESIZE
    16: RR_DEV
    25: 

So, is there a way to change those symbols before the batchMode executeMethod is called or do I need to do a special script to do this?

Hey there,

This will only help with your temporary solution. Instead of using text to find and replace the define symbols in the YAML scriptable singleton you can edit it with Unity’s own functionality. This script has not been tested but it should get you most of the way there.

// Load the Scriptable Singleton from disk. (it should only have one entry but YAML supports more then one)
object[] loadedObjects = InternalEditorUtility.LoadSerializedFileAndForget("ProjectSettings.asset");
// Create a serialized object to let use change it's settings. 
SerializedObject projectSettings = new SerializedObject(loadedObjects);
// Find the property we need to modify
var symbols = projectSettings.FindProperty("m_ScriptingDefineSymbols");
// Add a new element to the end
symbols.InsertArrayElementAtIndex(symbols.arraySize);
// Set the new element. 
symbols.GetArrayElementAtIndex(symbols.arraySize - 1) = "RR_DEV";
// Apply changes. 
projectSettings.ApplyModifiedProperties();
// Save it back to disk.
InternalEditorUtility.SaveToSerializedFileAndForget(projectSettings.targetObjects, "ProjectSettings.asset");

If you only need the defines set in the final app being built (i.e. in code for the game itself), just run the build. It will recompile the scripts whenever you call the Build Pipeline.

If your editor script that you’re running from the command line needs to be recompiled – stop doing that if at all possible. Pass in variables from the command line as arguments instead. You can use (for example, including a Build System Boolean Parameter that swaps between DEV and RELEASE):

-batchmode -quit +RR_DEV_{DEV} +RR_RELEASE_{RELEASE}

which might become:

-batchmode -quit +RR_DEV_true +RR_RELEASE_false

Then in your script, replace “#if RR_DEV” with:

string CommandLineArgs = Environment.GetCommandLineArgs();
if (CommandLineArgs.Contains(“+RR_DEV_true”)) {
// Do Dev stuff here, possibly including setting #RR_DEV for game code to compile under
}

The advantage to this is you can produce multiple build versions at the same time. For example, I make Dev, QA, and Release builds all in a single execution loop with different settings (and scripting defines) for each.

If you absolutely need to modify the scripting defines prior to execution of your Editor scripts, launch Unity twice in your build script. Run a Scripting Define Change function first, and the app build second.

You can use AddDefineSymbols to add define symbols automatically.

Features

  • Multiple Define Symbols
  • Safety
  • Runs when Compile ends
  • Removes Duplicates

Installation

  1. Download the Script or Copy/Paste it from the Below
  2. Open Script
  3. Go to Symbols property and add your own symbols
  4. Go back to Unity and wait for compile ends
  5. All done, now check Player Settings, The symbols added

Here is the code for copy/pasting:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
 
/// <summary>
/// Adds the given define symbols to PlayerSettings define symbols.
/// Just add your own define symbols to the Symbols property at the below.
/// </summary>
[InitializeOnLoad]
public class AddDefineSymbols : Editor
{
 
    /// <summary>
    /// Symbols that will be added to the editor
    /// </summary>
    public static readonly string [] Symbols = new string[] {
        "MYCOMPANY",
        "MYCOMPANY_MYPACKAGE"
    };
 
    /// <summary>
    /// Add define symbols as soon as Unity gets done compiling.
    /// </summary>
    static AddDefineSymbols ()
    {
        string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup ( EditorUserBuildSettings.selectedBuildTargetGroup );
        List<string> allDefines = definesString.Split ( ';' ).ToList ();
        allDefines.AddRange ( Symbols.Except ( allDefines ) );
        PlayerSettings.SetScriptingDefineSymbolsForGroup (
            EditorUserBuildSettings.selectedBuildTargetGroup,
            string.Join ( ";", allDefines.ToArray () ) );
    }
 
}

@rrsimon
any luck solving this issue ?
Thanks
Yury

did you find a correct way? I have the same problem like this.