Scripting Define Symbols - Access in code?

Hi,

I know in Unity4 it is now possible to create custom preprocessor defines for our scripts. The only way I know to define these is in the play build settings: http://docs.unity3d.com/Documentation/Components/class-PlayerSettings40.html

Is it possible to set the defines in a script? E.G through a menu option and then force Unity to recompile?

Thanks

Karl

1 Like

Did you ever find an answer for this?

It would be great for setting up build scripts…

PlayerSettings.SetScriptingDefineSymbolsForGroup can be used for set symbols in Editor Scripts.

You can find it at Unity - Scripting API: PlayerSettings.SetScriptingDefineSymbolsForGroup

1 Like

Thanks! That looks to be exactly what I wanted.

You could create an editor script which will set the values OnEnable() when scene will be opened.

You need to do:

  • Create an empty GameObject
  • Create a Monobehaviour script and add it to the empty GameObject ( I called it InitTest )
  • Create another script with extension Editor ( I called it InitTestEditor )
  • Add following code to the InitTestEditor, it doesn’t need to be attached to anything
using UnityEngine;

using UnityEditor;
using System.Collections;

[CustomEditor (typeof(InitTest))]
public class InitTestEditor : Editor {

    void OnEnable(){
        Debug.LogWarning("<b>TESTING</b> ADDED TO Scripting Define Symbols in <b>Player Settings</b>");
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone, "TESTING");
    }

}
3 Likes

Great @ocimum . Works perfect!

I added this ability to my plugin Custom Define Manager so you can call:

CustomDefineManager.DisableDirective()
CustomDefineManager.EnableDirective()
2 Likes

This actually wipes out any Scripting Define Symbols previously declared for the given platform.

1 Like

I have posted two methods that can deal with the define symbols in this thread:
https://forum.unity3d.com/threads/conditional-compiling-check-if-a-namespace-plugin-is-available-using-if-endif-c.477121

I’m using this below (to indicate to other scripts that my library is present).
This can be used safely on any platform (!), also it preserves other defines (!!!).

using System;
using UnityEngine;
using UnityEditor;


namespace Library
{


    [InitializeOnLoad]
    public class Library
    {


        const string define = "LIBRARY_IS_AVAILABLE";


        static Library()
        { AddLibrayDefineIfNeeded(); }

        static void AddLibrayDefineIfNeeded()
        {
            // Get defines.
            BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
            string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);

            // Append only if not defined already.
            if (defines.Contains(define))
            {
                Debug.LogWarning("Selected build target ("+EditorUserBuildSettings.activeBuildTarget.ToString()+") already contains <b>"+define+"</b> <i>Scripting Define Symbol</i>.");             
                return;
            }

            // Append.
            PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, (defines + ";" + define));
            Debug.LogWarning("<b>"+define+"</b> added to <i>Scripting Define Symbols</i> for selected build target ("+EditorUserBuildSettings.activeBuildTarget.ToString()+").");
        }
    }
}
4 Likes

Here is an advanced version, Just for fun. :stuck_out_tongue:
Features

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

Installation

  • Download the Script or Copy/Paste it from the Below
  • Open Script
  • Go to Symbols property and add your own symbols
  • Go back to Unity and wait for compile ends
  • All done, now check Player Settings, The symbols added
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 () ) );
    }

}

Thanks.

9 Likes

It seems there is a limit to how many symbols you can add. If you add too many, the last few are ignored by the preprocessor, and your code won’t compile. I’m in a situation where I need a lot of scripting define symbols, but haven’t found a solution yet.

Did anyone encounter this before?

Could you file a bug report?

Could you file a bug report? We should at least throw an error if the defines are going to be ignored.

1 Like

Why it is not working in this case?

       PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android,"ONE");
       Debug.Log("Set symbol " + PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android));
       Debug.Log("Application compiled");
#if One
        Debug.Log("One is defined");
#elif Ten
        Debug.Log("Ten is defined");
#endif

I am calling it from cmd
In the first call, it is not printing One is defined
when I am calling it again from cmd it is printing then.
Tried CompilerPipeLine.compilationFinished too.

Defines (technically conditional compilation symbols) are processed when the code is compiled - so you can’t set one and then expect it to be active on the next line, you need to wait for the code to be compiled again.