Conditional Compilation in Unity

We are spoiled by Unity with that whole “write once, run everywhere” thing. But what if we want to run different code on different platforms? Conditional compilation will come very handy here, or like Unity like to put it Platform Depended Compilation. ?

Wait, what’s that?

Great question! Conditional compilation is basically a way to tell the compiler to run code only if compiling condition is met.

Wait a moment. This sounds a lot of like a regular if-statement! What’s the catch?

Well, it kinda is, but at the same time isn’t. Like in if-statement we can decide when the code will be executed or not, but unlike in if-statement once the condition is not met, code that is in a statement will be stripped entirely at the compilation time.

Example

To better illustrate what I’m talking about, let me show you simple examples.

First, how we can easily alter the code to work differently on iOS and Android? We can use Application.platform in an if-statement.

using UnityEngine;

/// <summary>
/// This script show difference between if-statement and conditional compilation.
/// </summary>
public class DifferenceExample : MonoBehaviour
{
    /// <summary>
    /// Unity method called on first frame.
    /// </summary>
    void Start()
    {
        // Example built with regual if-statement
        if (Application.platform == RuntimePlatform.OSXEditor
            || Application.platform == RuntimePlatform.WindowsEditor
            || Application.platform == RuntimePlatform.LinuxEditor)
        {
            Debug.Log("You are running this code in the editor.");
        }

        if (Application.platform == RuntimePlatform.Android)
        {
            Debug.Log("This is Android platform.");
        }
        else if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
            Debug.Log("This is iOS platform.");
        }
    }
}

Easy, isn’t it? But with that, you are including code for both platforms in both builds for iOS and Android, or potentially on others too!

So let me present how you can do the same thing but with Conditional Compiling!

using UnityEngine;

/// <summary>
/// This script show difference between if-statement and conditional compilation.
/// </summary>
public class DifferenceExample : MonoBehaviour
{
    /// <summary>
    /// Unity method called on first frame.
    /// </summary>
    void Start()
    {
        // Example built with conditional compilation
#if UNITY_EDITOR
        Debug.Log("You are running this code in the ​editor.");
#endif

#if UNITY_ANDROID
        Debug.Log("This is Android platform.");
#elif UNITY_IOS
        Debug.Log("This is iOS platform.");
#endif
    }
}

That’s even simpler! ?

That approach will only include things that are related to the build platform, and it will strip the code that’s not!

Moreover, sometimes, plugins are written only for a specific platform, and they are unreachable on others. With conditional compilation, it’s not a problem as the code you’ve written will be only included on the provided platform!

Define your conditions!

Unity is providing us with their definitions, but we can also create our own!

There are two ways to do that in Unity.

1. File define

You can make a definition in the script, but you have to remember to put them in first lines of the file, even before usings!

#define EXAMPLE_DEBUG // <- My custom​ define, works only within this file.
using UnityEngine;

/// <summary>
/// This script show how you can use conditional compilation in development.
/// By commenting out the first line you are disabling all Debug Logs from this script.
/// </summary>
public class DebugDefineExample : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
#if EXAMPLE_DEBUG
        Debug.LogFormat("{0} TriggerEnter by {1}", gameObject, other.gameObject);
#endif
    }

    private void OnTriggerStay(Collider other)
    {
#if EXAMPLE_DEBUG
        Debug.LogFormat("{0} TriggerStay by {1}", gameObject, other.gameObject);
#endif
    }

    private void OnTriggerExit(Collider other)
    {
#if EXAMPLE_DEBUG
        Debug.LogFormat("{0} TriggerExit by {1}", gameObject, other.gameObject);
#endif
    }
}

I’m often using this version to enable and disable debug logs when I’m programming or testing. When I’m finished, I can simply comment out the definition, and my logs won’t appear in the console. ?

With this approach, this definition will work only in a file that it is defined in, which could be pro and con at the same time. ?

2. Project define

This definition will work across all of your scripts, so use case for them might be enabling or disabling whole systems in your game.

To add new definitions to your project, you need to go to the Player Settings, and find Scripting Define Symbols field.

Scripting Define Symbols in Player Settings

Here you can only add or remove definitions for your entire project for a given platform.

Great! I hope you’ve learned something useful for yourself. ?

If you want to continue reading, I have a post about a few Design Patterns that you can use in development!

As always, my code is available on my public repository. ?

See you next time around! ?

3.5 2 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x