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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Preprocessing identifier Conditional attribute

Discussion in 'Editor & General Support' started by Redtail87, Jun 3, 2014.

  1. Redtail87

    Redtail87

    Joined:
    Jul 17, 2013
    Posts:
    125
    Hey there,

    I am using some compiler conditionals with platforms and saw in the documentation here that you can use the Conditional attribute like this. I can not seem to get it to work though, if I put it before the function it still compiles.

    for example:

    Code (csharp):
    1.  
    2.         [System.Diagnostics.Conditional("UNITY_ANDROID")]
    3.         static void Test(string fileName)
    4.         {
    5.             string filePath = Application.persistentDataPath + "/" + fileName;
    6.             WWW load = new WWW("test");
    7.             System.IO.File.WriteAllBytes(filePath, load.bytes);
    8.         }
    9.  
    Gives the error for the WriteAllBytes function when in web build mode in the editor

    but this does work while in web platform in the editor without editors like it should

    Code (csharp):
    1.  
    2. #if UNITY_ANDROID
    3.         static void Test(string fileName)
    4.         {
    5.             string filePath = Application.persistentDataPath + "/" + fileName;
    6.             WWW load = new WWW("test");
    7.             System.IO.File.WriteAllBytes(filePath, load.bytes);
    8.         }
    9. #endif
    10.  
    Am I doing something wrong here?
     
    Japsu likes this.
  2. Simon Says

    Simon Says

    Joined:
    Feb 23, 2013
    Posts:
    6
    Yeah, it looks like the ConditionalAttribute only works for custom defines. It works as expected with my own defines, but when it comes to standard platform symbols like "UNITY_EDITOR", I have no luck neither. Kind of a bummer.
     
  3. Simon Says

    Simon Says

    Joined:
    Feb 23, 2013
    Posts:
    6
    I just realized after reading this: http://stackoverflow.com/questions/3788605/if-debug-vs-conditionaldebug that it's actually expected behaviour. You see, only calls are stripped, but methods are still compiled into IL. And at this point your System.IO.File.WriteAllBytes() simply doesn't exist. It doesn't matter that the method is never going to be called in the resulting code. The compiler doesn't know. Still a bummer though.
     
    SolidAlloy and idbrii like this.
  4. Simon Says

    Simon Says

    Joined:
    Feb 23, 2013
    Posts:
    6
    By the way, the solution is obvious (for anyone who reads this later). Just wrap the inside of the problematic method in #if directive like this:

    Code (CSharp):
    1. [System.Diagnostics.Conditional("UNITY_ANDROID")]
    2. static void Test(string fileName)
    3. {
    4. #if UNITY_ANDROID
    5.        string filePath = Application.persistentDataPath + "/" + fileName;
    6.        WWW load = new WWW("test");
    7.        System.IO.File.WriteAllBytes(filePath, load.bytes);
    8. #endif
    9. }
    10.  
    And you can call Test() anywhere else without worries.
     
    zander_m likes this.
  5. taxvi

    taxvi

    Joined:
    Feb 18, 2013
    Posts:
    30
    In this case the `Conditional` attribute looses the purpose
     
  6. iSinner

    iSinner

    Joined:
    Dec 5, 2013
    Posts:
    201
    Not really, it saves you the overhead of calling an empty method when the platform, in this specific example, isn't android.
     
  7. Baydogan

    Baydogan

    Joined:
    Mar 22, 2018
    Posts:
    54
    No, maybe your understanding is wrong for the "purpose of conditional attribute" or you only need the preprocessor define.

    The conditional attribute has no effect on the callee side, it works on the caller side.

    The code for the method will compile and will be included in the IL level, however, calls to the method will be omitted if the preprocessor define is not set on the caller side.

    TLDR:

    If you do not want the code to compile to the IL use the following:

    Code (CSharp):
    1. #if UNITY_ANDROID
    2.     //----
    3. #endif
    If you want the code to compile to the IL but execute it in some places and not execute it in other places conditionally use the following:

    Code (CSharp):
    1. [System.Diagnostics.Conditional("UNITY_ANDROID")]
     
    Last edited: Feb 11, 2023
    CasimmVancouver likes this.
  8. OUTTAHERE

    OUTTAHERE

    Joined:
    Sep 23, 2013
    Posts:
    656
    Yeah, that defies the purpose.
    Now you have to pepper #ifdefs throughout your code.
    It could, COMPLETELY LEGALLY, compile, and then be stripped on the IL level.
    But no. We cannot have nice things.
    (or, you know, UnityEditor could just be a stub Assembly for builds)
    (especially in ECS baking, this is so densely mixed, and you can't just put your Authoring Behaviours into Editor folders, because Unity made that Maliciously illegal as well - can't have editor scripts on game objects, even though there are about a dozen very concrete use cases for them)