この記事でのバージョン
Unity 2019.1.0a8
はじめに
今回はコンパイルの開始と終了を検知する方法のご紹介です。
ちなみにUnityではプログラムを修正し、コンパイルが開始されると右下にアイコンが表示されます。
なので、このアイコンが表示された時と消えた時を検知しようという感じです。
イメージとしては以下のような感じ
compilationStartedとcompilationFinished
コンパイルの開始と終了を検知したい時はCompilationPipelineを使うと便利です。
使い方は簡単、compilationStartedとcompilationFinishedというイベントにメソッドを登録するだけ。
using UnityEditor; using UnityEditor.Compilation; using UnityEngine; [InitializeOnLoad]//エディター起動時に初期化されるように public static class CompilationPipelineExample { //================================================================================= //初期化 //================================================================================= /// <summary> /// コンストラクタ(InitializeOnLoad属性によりエディター起動時に呼び出される) /// </summary> static CompilationPipelineExample() { //CompilationPipelineの各イベントにメソッド登録 CompilationPipeline.compilationStarted += OnCompilationStarted; CompilationPipeline.compilationFinished += OnCompilationFinished; } //================================================================================= //全体のコンパイル開始と終了の検知 //================================================================================= //全体のコンパイル開始時に呼ばれる private static void OnCompilationStarted(object obj){ Debug.Log("全体のコンパイル開始"); } //全体のコンパイル終了時に呼ばれる private static void OnCompilationFinished(object obj) { Debug.Log("全体のコンパイル終了"); } }
ただし、この2つのイベントはUnity2019.1で追加されたものなので、それ以前では使えません。
(EditorApplication.isCompilingを使えば検知自体は可能です。)
なお、引数のobjectはドキュメントに以下のように書いてあるので、
Context object can be used to match CompilationPipeline.compilationStarted and CompilationPipeline.compilationFinished events.
Google翻訳
Contextオブジェクトを使用して、CompilationPipeline.compilationStartedイベントとCompilationPipeline.compilationFinishedイベントを一致させることができます。
Unity - Scripting API: Compilation.CompilationPipeline.compilationStarted
開始と終了のイベントを一致させるために使うようです。
おそらくコンパイル中に新たなコンパイルが発生しても混同しないようにするためのものだと思います。
//コンパイル開始時のオブジェクト private object _startObj = null; //全体のコンパイル開始時に呼ばれる private static void OnCompilationStarted(object obj){ Debug.Log("全体のコンパイル開始"); _startObj = obj; } //全体のコンパイル終了時に呼ばれる private static void OnCompilationFinished(object obj) { Debug.Log("全体のコンパイル終了"); //開始と終了が一致しているか(同じコンパイルか) if(_startObj == obj){ } }
assemblyCompilationStartedとassemblyCompilationFinished
CompilationPipelineには
assemblyCompilationStartedとassemblyCompilationFinishedというイベントもあり、
これを使えば各アセンブリごとのコンパイルの開始と終了を検知する事が出来ます。
なお、ここで言うアセンブリとは複数のファイルをまとめたもの(ライブラリアセンブリ : DLL)の事で、
例えばEditorという特殊フォルダのファイルはAssembly-CSharp-Editor.dll、
それ以外の特殊じゃないフォルダのファイルはAssembly-CSharp.dllというアセンブリにまとめられます。
余談ですが、Assembly Definition Filesを使えばアセンブリを任意に分割する事も可能です。
使い方は先程と同様にイベントにメソッドを登録するだけ。
using UnityEditor; using UnityEditor.Compilation; using UnityEngine; [InitializeOnLoad]//エディター起動時に初期化されるように public static class CompilationPipelineExample { //================================================================================= //初期化 //================================================================================= /// <summary> /// コンストラクタ(InitializeOnLoad属性によりエディター起動時に呼び出される) /// </summary> static CompilationPipelineExample() { //CompilationPipelineの各イベントにメソッド登録 CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted; CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished; } //================================================================================= //各コンパイル開始と終了の検知 //================================================================================= //各コンパイル開始時に呼ばれる private static void OnAssemblyCompilationStarted(object obj) { Debug.Log(obj + "のコンパイル開始"); } //各コンパイル終了時に呼ばれる private static void OnAssemblyCompilationFinished(object obj, CompilerMessage[] messages) { Debug.Log(obj + "のコンパイル終了"); //警告やエラー等のメッセージがあればログで表示 foreach (CompilerMessage compilerMessage in messages) { Debug.Log(compilerMessage.type.ToString() + "\n" + compilerMessage.message); } } }
なお上記のコードの通り、エラーや警告を検知する事も可能です。
------------追記------------
CompilationPipelineを使って、
アセンブリごとのコンパイル時間を計測したり、閾値を越えたら警告を出したりするやつを作りました!
------------追記おわり------------