はじめに
もしUnityを扱ったことのある方は以下のようなコードをみたことはないでしょうか。
#if UNITY_EDITOR Debug.Log("Unity Editor"); #endif
#if ~ #endifの中にあるDebug.LogはUnityのエディタのときのみコンパイル,実行されます。
これらは別にUnity特有の機能というわけではなく、C#の機能です。
今回はこの#ifについて取り上げていきたいと思います。
#ifディレクティブ
冒頭でも述べましたが、#ifと#endifの両ディレクティブで囲まれたコードの条件付きコンパイルが行えます。
書き方としては、#ifディレクティブの後ろのシンボル式を書きます。
#define SAMPLE1 // #define SAMPLE2 using System; class Program { static void Main(string[] args) { #if SAMPLE1 Console.WriteLine("こっちはコンパイルされる"); #endif #if SAMPLE2 Console.WriteLine("こっちはコンパイルされない"); #endif } }
また演算子を使った書き方もできます。
#define SAMPLE1 // #define SAMPLE2 using System; class Program { static void Main(string[] args) { #if SAMPLE1 || SAMPLE2 Console.WriteLine("こっちはコンパイルされる"); #endif #if SAMPLE1 != SAMPLE2 Console.WriteLine("こっちはコンパイルされる"); #endif #if !SAMPLE1 Console.WriteLine("こっちはコンパイルされない"); #endif #if SAMPLE1 && SAMPLE2 Console.WriteLine("こっちはコンパイルされない"); #endif } }
Conditional属性
#ifの場合、たくさんの箇所に使うのはなかなか骨が折れます。
そういった問題を軽減するためにConditional属性を使うことで条件付きメソッドを作成することができます。
#define DEBUG public static class Debug { [Conditional("DEBUG")] public static void Log(string message) => Console.WriteLine(message); }
もしデバック用の出力をDebug.Logで活用するように徹底していれば、簡単に出力を実行するかしないか決めることができます。
ただし一番の落とし穴は条件付きメソッド自体は常にコンパイルされ、呼び出し部分のみコンパイルされない仕組みになっていることです。
つまり#ifの代用として使えますが、少し性質が異なること(例えばファイルのサイズが増える等)に注意してください。
さいごに
UnityでもDebug.Logをリリースビルドに含めてしまうのを防ぐためにどうすれば良いかという議論がよくあります。
そもそも UnityのDebug.Logが重いのはスタックトレースに時間がかかっているからであり,Project Settingにて変更ができたはずなので今回紹介したものはさほど必要ないかもしれません。
ただ色々な場面で利用できるので、覚えておいても損はないと思います。
是非うまく活用してみてください。
ではまた。