【Unity】EditorWindowのOnEnableはコンパイル時にも呼ばれるという話

EditorWindowのOnEnableはWindowを開いた時だけでなく
スクリプトコンパイル時にも呼ばれるという話です。

問題点

Windowの初期化処理をOnEnableに書くことはあるかと思います。

例としてOnEnableで選択中のオブジェクトを収集してみます。
OnGUIではそのオブジェクトの名前を描画します。

using UnityEngine;
using UnityEditor;

public class ExampleWindow : EditorWindow 
{
    private Object _selected;

    [MenuItem("Window/Example Window")]
    private static void Open()
    {
        GetWindow<ExampleWindow>("Example");
    }

    private void OnGUI()
    {
        EditorGUILayout.LabelField("NAME : " + _selected.name);
    }

    private void OnEnable()
    {
        _selected       = Selection.activeObject;
    }
}

何かを選択した状態でこのWindowを開くと正常に動作します。

f:id:halya_11:20181212131727p:plain

ここで何も選択していない状態にしてから、適当に何かしらのソースコードを変えて再コンパイルします。
すると、オブジェクトがnullだといわれます。

原因と対策

原因はシンプルで、EditorWindowのOnEnableがコンパイルが走った時にも呼ばれるからです。

なのでソースコードは次のように修正します。

using UnityEngine;
using UnityEditor;

public class ExampleWindow : EditorWindow 
{
    private Object _selected;
    private bool _didInitiaze;

    [MenuItem("Window/Example Window")]
    private static void Open()
    {
        GetWindow<ExampleWindow>("Example");
    }

    private void OnGUI()
    {
        EditorGUILayout.LabelField("NAME : " + _selected.name);
    }

    private void OnEnable()
    {
        // 再コンパイル時に処理したくないので初期化チェック
        if (!_didInitiaze) {
            _selected       = Selection.activeObject;
            _didInitiaze    = true;
        }
    }
}

これでコンパイル時に処理が走らなくなりました。