LoginSignup
7
7

More than 5 years have passed since last update.

プリプロセッサの代わりにConditionalAttributeを使う

Last updated at Posted at 2018-05-08

 Unityの環境別プログラミングに便利そうなConditionalAttributeを使ってみました。Editor上のみで使う関数、Androidのみで使う関数、といった記述をスマートに行えます。
参考:http://d.hatena.ne.jp/nakamura001/20151202/1449029637

長所1 プリプロセッサよりも可読性が高い

 プリプロセッサを使ったサンプルコードと、ConditionalAttributeを使ったサンプルコードを比べてみましょう。まず、プリプロセッサを使った場合。

using UnityEngine;

public class TestPreprocessor : MonoBehaviour
{
    void Start ()
    {
#if UNITY_ANDROID
        TestAndroid();
#endif
#if UNITY_WEBGL
        TestWebgl();
#endif
#if UNITY_EDITOR
        TestEditor();
#endif
    }

#if UNITY_ANDROID
    void TestAndroid()
    {
        Debug.Log("Android");
    }
#endif

#if UNITY_WEBGL
    void TestWebgl()
    {
        Debug.Log("WebGL");
    }
#endif

#if UNITY_EDITOR
    void TestEditor()
    {
        Debug.Log("Editor");
    }
#endif
}

 単純な記述なのでまだ読めます。しかし、長大な処理になると、終点のendifが見当たらないまま読むことになったりして快適さはかなり損なわれます。続いて、ConditionalAttributeを使った場合。

using UnityEngine;

public class TestConditional : MonoBehaviour
{
    void Start ()
    {
        TestAndroid();
        TestWebgl();
        TestEditor();
    }

    [System.Diagnostics.Conditional("UNITY_ANDROID")]
    void TestAndroid()
    {
        Debug.Log("Android");
    }

    [System.Diagnostics.Conditional("UNITY_WEBGL")]
    void TestWebgl()
    {
        Debug.Log("WebGL");
    }

    [System.Diagnostics.Conditional("UNITY_EDITOR")]
    void TestEditor()
    {
        Debug.Log("Editor");
    }
}

 かなりスッキリしたのではないでしょうか。呼び出し元に分岐条件を書く必要が無いので記述も楽です。ただ、分岐記述が無い分、特定環境下でしか呼ばれないことがわかりにくいので、ちょっとコメントを追加する必要があるかな、と思います。

長所2 プリプロセッサで引き起こされるコンパイルエラーが無い

 Editorのみで使う関数をプリプロセッサで囲い忘れてコンパイルエラー、というのはプリプロセッサを使ってたら一度は遭遇すると思います。GitのメインブランチにMergeした後にCIツールがコンパイルエラーで動かなくなって気まずい思いをしたことが自分はあります。ConditionalAttributeでは前述のように呼び出し元については自動でSkipされるので、その心配はありません。

短所1 if not的な記述をできない

 iOS以外、Editor以外、みたいな記述はできないようです。プリプロセッサはelse節があるので可能です。
参考: https://stackoverflow.com/questions/8230191/c-sharp-conditional-attribute

短所2 通常MethodとAttributeクラスにしか使えない

 interfaceに対しては使えません。Constructor、Destructor、Operator、interface指定Methodにも使えません。interfaceに使えれば、Editor上でしか使わないinterfaceを用意して色々できそうだったのですが残念です。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7