Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
7
Question by jimbobuk · Dec 22, 2009 at 01:12 AM · debugpreprocessor

Is there a way to have debug code compiled out for a final build?

Is there an equivalent to the C standard way of having debug code that is disabled or compiled out for a final release build?

In C you would do something like

#if !RELEASEBUILD
... debug code ...
#endif

I expect this to be a bit of a problem with Unity/Mono but thought i'd ask. If it isn't possible then i'll just write some awk scripts that i can run which will allow for the same kind of behavior by manually running it on my script files before doing a final build.

Cheers

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image yoyo · Nov 12, 2014 at 10:45 PM 0
Share

As of Unity 4.1 you can now add your own project-wide defines, see my answer below.

5 Replies

· Add your reply
  • Sort: 
avatar image
6

Answer by jashan · Dec 22, 2009 at 08:54 AM

As Peter pointed out: Currently, Unity doesn't support project-wide #defines, which in my opinion is a very unfortunate limitation. One thing you can do to get this more into reach is vote up the entry on feedback.unity3d.com: Editor: Interface for listing preprocessor macros (#define) in build settings. With that feature, the issue (and a lot more issues) would be solved.

One thing you could do under "the right circumstances" is compiling DLLs with Visual Studio that you use in Unity. That way, you could use the defines from Visual Studio. Unfortunately, those "right circumstances" are probably quite rare (usually, you'll want to keep most code directly in the Unity project because it simplifies most things).

So, until I get those defines in Unity, what I'm doing is this: I have a couple of defines in every class file where I need them, and I also have a script that runs through all the classes and does a little bit of code replacement to either "activate" or "deactivate" those code sections (I comment them in/out via script). That way, I have "kind of the same functionality" as I would have with proper project wide defines. It's just a hack and somewhat more cumbersome ... but it works for me in a rather complex project (server/client, different client versions etc.)

The whole code that I'm using for this is a bit too much and too complex (and too unpolished) to post but I can give you a few bits that should be helpful to set something like that up for yourself. So, the code I'm posting here is not "easy copy'n'paste code" but it should get you start it - and feel to ask questions (I can still edit this to make things more clear).

Just a word of warning: Replacing code in your source files can ruin your project if you're not careful. I also had a lot of Unity crashes when I developed this (but that was with a much older version of Unity). So either use version control (like the Asset Server) or always keep backup copies. And, speaking of version control: doing these replacements will obviously change your code; and usually, that's not a change you'd usually want to record in your version control - so in most cases, you'll probably just do this for a build and then revert the changes.

That said:

// Activate / deactivate the debug symbol (somewhere in an editor script or console app) public void ConfigureDebugCode(bool isDebug) { ConfigurationHelper helper = new ConfigurationHelper(); helper.RegisterIncludeSymbol("DEBUG", isProduction); helper.ReplaceInAllScriptAssets(); }

// I have this in a separate class; this has a "CONSOLEAPP"-define public class ConfigurationHelper {

 private string fileFilter = "*.cs";

 private List<string[]> currentReplacements = new List<string[]>(9);

 public void RegisterIncludeSymbol(string symbol, bool activate) {
      string a = string.Format("#define {0} //A", symbol);
      string b = string.Format("//#define {0} //I", symbol);
      RegisterReplaceAwithB(a, b, activate);
 }

 public void RegisterReplaceAwithB(string a, string b, bool revert) {
     if (revert) {
         currentReplacements.Add(new string[] { b, a });
     } else {
         currentReplacements.Add(new string[] { a, b });
     }
 }

 // the following is what I called "unpolished" ;-)

 /// <summary>
 ///     Executes the replacements that were previously registered.
 /// </summary>
 public void ReplaceInAllScriptAssets() {
     if (currentReplacements.Count == 0) {

if CONSOLEAPP

        Console.WriteLine("ReplaceInAllScriptAssets without registering replacements, not replacing anything!");

else

        Debug.LogWarning("ReplaceInAllScriptAssets without registering replacements, not replacing anything!");

endif

        return;
     }

     //Debug.Log("Will be replacing:");
     //foreach (string[] replace in currentReplacements) {
     //    Debug.Log(string.Format("{0} / {1}", replace[0], replace[1]));
     //}

if CONSOLEAPP

    DirectoryInfo assets = new DirectoryInfo(ProjectPath + "Assets/");

else

    DirectoryInfo assets = new DirectoryInfo("Assets/");

endif

    List<FileInfo> changedFiles = new List<FileInfo>();
     FileInfo[] scripts = assets.GetFiles(fileFilter, SearchOption.AllDirectories);
     int index = assets.FullName.Length - "Assets/".Length;
     for (int i=0; i < scripts.Length; i++) {
         FileInfo script = scripts[i];

if !CONSOLEAPP

        EditorUtility.DisplayProgressBar("Replacing keys in files", 
             string.Format("File: {0}", script.FullName.Substring(index)), 
             ((float) i) / ((float) scripts.Length));

endif

        if (script.FullName.Contains("Editor")) { 
             // we don't want to mess with editor scripts (like this one ;-) )
             //Debug.Log(string.Format("Ignoring editor script: {0}", script.Name));
         } else if (script.FullName.Contains("Standard Assets")) {
             // we also don't want to mess with scripts from (Pro) Standard Assets
             //Debug.Log(string.Format("Ignoring (Pro) Standard Assets script: {0}", script.Name));
         } else { // now here's the gold ;-)
             //Debug.Log(string.Format("Processing file: {0}", script.FullName.Substring(index)));

             StreamReader reader = script.OpenText();
             string code = reader.ReadToEnd();
             reader.Close();

             string newCode = code;
             foreach (string[] replace in currentReplacements) {
                 newCode = newCode.Replace(replace[0], replace[1]);
             }
             if (!code.Equals(newCode) /* code.GetHashCode() != newCode.GetHashCode()*/) {
                 script.Refresh();
                 changedFiles.Add(script);
                 StreamWriter writer = new StreamWriter(script.Open(FileMode.Create), Encoding.UTF8); // "overwrite"
                 writer.Write(newCode);
                 writer.Flush();
                 writer.Close();
             }
         }
     }

     //allReplacements.AddRange(currentReplacements);
     currentReplacements.Clear();

if !CONSOLEAPP

    EditorUtility.ClearProgressBar();

     StringBuilder filesWithReplacements = new StringBuilder("Replacing codes in all scripts DONE!\n");

     AssetDatabase.StartAssetEditing();
     foreach (FileInfo script in changedFiles) {
         MonoScript scriptObject = (MonoScript)AssetDatabase.LoadAssetAtPath(script.FullName.Substring(index), typeof(MonoScript));
         if (scriptObject != null) {
             // this should make sure this is recompiled before build...
             EditorUtility.SetDirty(scriptObject);

             // is that really needed? I left it in here just to be sure...
             AssetDatabase.ImportAsset(script.FullName.Substring(index), ImportAssetOptions.Default);
             //AssetDatabase.ImportAsset(script.FullName.Substring(index), ImportAssetOptions.ForceSynchronousImport);
             //Thread.Sleep(100);
             filesWithReplacements.AppendLine(script.FullName.Substring(index));
         } else {
             Debug.LogWarning(string.Format("Could not open {0} as asset!", script.FullName.Substring(index)));
         }
     }
     AssetDatabase.StopAssetEditing();

     Debug.Log(filesWithReplacements.ToString());

endif

}

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jimbobuk · Dec 22, 2009 at 12:16 PM 0
Share

Thanks for this. Very detailed. I wasn't aware that even #if was allowed syntax. That helps a little.

I may have a go at writing a simple awk script as i don't foresee needing too much flexibility yet, I was thinking a similar thing though, to comment out the blocks i don't want.

I'll happily vote up this request, looks like i need a new account again, and unlike unity answers you can't authenticate via the unity forums it seems.

Cheers

avatar image jashan · Dec 22, 2009 at 04:45 PM 0
Share

Originally, I had blocks commented in/out - but that turned out to be quite a bit more cumbersome than the approach using commenting in/out just the defines. So, I converted all my "special syntax comments" to actual #ifs and now I'm almost happy ;-) Oh ... an regarding feedback.unity3d.com: I think you can also use OpenID with the forums (like here).

avatar image Martian-Games · Apr 09, 2014 at 10:16 PM 0
Share

Please edit your link to read "feedback.unity3d.com" .. with "unity" spelled correctly, currently your unit3d link points us to a nasty Trojan site :/ otherwise, thanks for the help! :D

avatar image yoyo · Apr 13, 2014 at 02:19 AM 0
Share

Good catch, I just fixed the link.

avatar image
4

Answer by Peter Alexander · Dec 22, 2009 at 01:20 AM

That isn't strictly possible with Unity as it doesn't support project-wide #defines like Visual Studio does.

You can, of course, do something like the following:

if (MyGameSettings.Debug)
{
    ...
}

and if Debug is declared as const and is false then the inner code will not become part of the binary.

That works for most cases, but if you need to strip out entire classes then you'll need another solution. You could easily write a script to process all your source files to handle the task.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jimbobuk · Dec 22, 2009 at 02:18 AM 0
Share

I can certainly get by without being able to do entire classes for now. So can we prove what you are saying here that it WILL be compiled out if its const and false? That does sound like all i need.

I may write a script anyways to be absolutely sure, but i'd be interested if anyone could prove what you are saying by looking at the binary sizes.

Cheers

avatar image Peter Alexander · Dec 22, 2009 at 02:30 AM 0
Share

It has been proven before. You can look at the disassembled CIL instructions using ILDAS$$anonymous$$ to see that the enclosed instructions are missing. It is very important that you declare the Debug variable as const, otherwise the compiler cannot reliable perform this optimisation. If everything goes well, you should also receive a 'Found unreachable code' warning in the Unity console.

avatar image
4

Answer by yoyo · Oct 02, 2012 at 03:51 PM

[EDIT]

As of Unity 4, it is possible to create your own project-wide (and platform-specific) preprocessor defines in the Player Settings, as documented here.


[OLD ANSWER]

Note that you can check Debug.isDebugBuild to see if you are currently running a development build (based on the corresponding checkbox in the build settings). This is a runtime check, so code does not get compiled out as the OP requested.

You can also mark classes or methods with the ConditionalAttribute, which tells the compiler to remove code (and calls to it) unless a specific pre-processor define is present. Here's what it looks like:

 using System.Diagnostics;
 #define DEBUG
 
 [Conditional("DEBUG")]
 class MyConditionalClass
 {
     ...
 }
 

This would be much more useful if Unity provided more control over pre-processor defines. (Note that Profiler.BeginSample uses this mechanism to strip profiling hooks from non-development builds. Internally they are using the ENABLE_PROFILER #define, which is perhaps a way to tell if you are in a development build. Probably works for Unity Pro only.)

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by codestage · Jul 22, 2015 at 03:28 PM

Sorry for bumping so outdated question, but for any future visitors: you may use DEVELOPMENT_BUILD conditional flag, just like this for example:

 #if DEVELOPMENT_BUILD
     private void OnGUI()
     {
         // your debug GUI here
     }
 #endif
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by ian.du · Feb 17, 2010 at 06:15 PM

What does Unity / Mono do in the slightly less obvious case:

    if(InputState.RUN_STATE_MACHINE && InputState.SHOW_DEBUG_MESSAGE){
        ....
    }

when InputState.RUN_STATE_MACHINE is const FALSE and InputState.SHOW_DEBUG_MESSAGE in not const ???

To a human this is clearly always going to evaluate to FALSE, and so the compiler should strip the entire code block out. However, from my experience, it is almost always possible to trick a compiler into evaluating a statement repeatedly, even if the statement is always FALSE.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

2 People are following this question.

avatar image avatar image

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

What C# predefines are recognized by Unity? 3 Answers

Debug Rendering using the depth buffer 3 Answers

My script isn't working - what are some ways I can start debugging? 7 Answers

Debug.Log doesn't get called when Unity freezes? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges