コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】エディタ拡張で使用できるコールバックを40個まとめて紹介

はじめに

この記事では Unity のエディタ拡張で使用できる
コールバック用のデリゲートやインターフェイス、属性を
公式ドキュメントに記載されていないモノも含めて40個紹介していきます

目次

※公式ドキュメントに記載されていないモノには★が付いています

デリゲート

★Unity プロジェクトを読み込んだ時

  • EditorApplication.projectWasLoaded
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;

[InitializeOnLoad]
public static class EditorApplicationUtility
{
    private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly FieldInfo m_info = typeof( EditorApplication ).GetField( "projectWasLoaded", BINDING_ATTR );

    public static UnityAction projectWasLoaded
    {
        get
        {
            return m_info.GetValue( null ) as UnityAction;
        }
        set
        {
            var functions = m_info.GetValue( null ) as UnityAction;
            functions += value;
            m_info.SetValue( null, functions );
        }
    }
}

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplicationUtility.projectWasLoaded += () =>
        {
            Debug.Log( "projectWasLoaded" );
        };
    }
}

★Unity エディタを終了した時

  • EditorApplication.editorApplicationQuit
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;

[InitializeOnLoad]
public static class EditorApplicationUtility
{
    private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly FieldInfo m_info = typeof( EditorApplication ).GetField( "editorApplicationQuit", BINDING_ATTR );

    public static UnityAction editorApplicationQuit
    {
        get
        {
            return m_info.GetValue( null ) as UnityAction;
        }
        set
        {
            var functions = m_info.GetValue( null ) as UnityAction;
            functions += value;
            m_info.SetValue( null, functions );
        }
    }
}

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplicationUtility.editorApplicationQuit += () =>
        {
            Debug.Log( "editorApplicationQuit" );
        };
    }
}

★アセットのラベルが変更された時

  • EditorApplication.assetLabelsChanged
using System.Reflection;
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public static class EditorApplicationUtility
{
    private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly FieldInfo m_info = typeof( EditorApplication ).GetField( "assetLabelsChanged", BINDING_ATTR );

    public static EditorApplication.CallbackFunction assetLabelsChanged
    {
        get
        {
            return m_info.GetValue( null ) as EditorApplication.CallbackFunction;
        }
        set
        {
            var functions = m_info.GetValue( null ) as EditorApplication.CallbackFunction;
            functions += value;
            m_info.SetValue( null, functions );
        }
    }
}

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplicationUtility.assetLabelsChanged += () =>
        {
            Debug.Log( "assetLabelsChanged" );
        };
    }
}

★アセットのアセットバンドル名が変更された時

  • EditorApplication.assetBundleNameChanged
using System.Reflection;
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public static class EditorApplicationUtility
{
    private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly FieldInfo m_info = typeof( EditorApplication ).GetField( "assetBundleNameChanged", BINDING_ATTR );

    public static EditorApplication.CallbackFunction assetBundleNameChanged
    {
        get
        {
            return m_info.GetValue( null ) as EditorApplication.CallbackFunction;
        }
        set
        {
            var functions = m_info.GetValue( null ) as EditorApplication.CallbackFunction;
            functions += value;
            m_info.SetValue( null, functions );
        }
    }
}

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplicationUtility.assetBundleNameChanged += () =>
        {
            Debug.Log( "assetBundleNameChanged" );
        };
    }
}

★Unity エディタ上で何か操作された時

  • EditorApplication.globalEventHandler
using System.Reflection;
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public static class EditorApplicationUtility
{
    private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly FieldInfo m_info = typeof( EditorApplication ).GetField( "globalEventHandler", BINDING_ATTR );

    public static EditorApplication.CallbackFunction globalEventHandler
    {
        get
        {
            return m_info.GetValue( null ) as EditorApplication.CallbackFunction;
        }
        set
        {
            var functions = m_info.GetValue( null ) as EditorApplication.CallbackFunction;
            functions += value;
            m_info.SetValue( null, functions );
        }
    }
}

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplicationUtility.globalEventHandler += () =>
        {
            Debug.Log( "globalEventHandler" );
        };
    }
}

★Unity エディタの各ウィンドウの位置が変更された時

  • EditorApplication.windowsReordered
using System.Reflection;
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public static class EditorApplicationUtility
{
    private const BindingFlags BINDING_ATTR = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly FieldInfo m_info = typeof( EditorApplication ).GetField( "windowsReordered", BINDING_ATTR );

    public static EditorApplication.CallbackFunction windowsReordered
    {
        get
        {
            return m_info.GetValue( null ) as EditorApplication.CallbackFunction;
        }
        set
        {
            var functions = m_info.GetValue( null ) as EditorApplication.CallbackFunction;
            functions += value;
            m_info.SetValue( null, functions );
        }
    }
}

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplicationUtility.windowsReordered += () =>
        {
            Debug.Log( "windowsReordered" );
        };
    }
}

Project ビューの表示をカスタマイズする時

  • EditorApplication.projectWindowItemOnGUI
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.projectWindowItemOnGUI += ( guid, selectionRect ) =>
        {
            var rect = selectionRect;
            rect.width = 20;
            rect.x = selectionRect.xMax - 20;
            if ( !GUI.Button( rect, "!!" ) ) return;
            Debug.Log( "projectWindowItemOnGUI" );
        };
    }
}

Hierarchy の表示をカスタマイズする時

  • EditorApplication.hierarchyWindowItemOnGUI
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.hierarchyWindowItemOnGUI += ( instanceID, selectionRect ) =>
        {
            var go = EditorUtility.InstanceIDToObject( instanceID ) as GameObject;
            if ( go == null ) return;
            var pos = selectionRect;
            pos.x = pos.xMax - 16;
            pos.width = 16;
            var newActive = GUI.Toggle( pos, go.activeSelf, string.Empty );
            if ( newActive == go.activeSelf ) return;
            go.SetActive( newActive );
        };
    }
}

1秒間に200回呼び出される

  • EditorApplication.update
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.update += () =>
        {
            Debug.Log( "update" );
        };
    }
}

エディタの更新が完了した時

  • EditorApplication.delayCall
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.delayCall += () =>
        {
            Debug.Log( "delayCall" );
        };
    }
}

シーン内のオブジェクトが変更された時

  • EditorApplication.hierarchyWindowChanged
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.hierarchyWindowChanged += () =>
        {
            Debug.Log( "hierarchyWindowChanged" );
        };
    }
}

Project ビューで何か変更された時

  • EditorApplication.projectWindowChanged
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.projectWindowChanged += () =>
        {
            Debug.Log( "projectWindowChanged" );
        };
    }
}

Scen ビューや Hierarchy の検索欄の文字列が変更された時

  • EditorApplication.searchChanged
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.searchChanged += () =>
        {
            Debug.Log( "searchChanged" );
        };
    }
}

キー入力された時

  • EditorApplication.modifierKeysChanged
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.modifierKeysChanged += () =>
        {
            Debug.Log( "modifierKeysChanged" );
        };
    }
}

Unity の再生状態が変更された時

  • EditorApplication.playmodeStateChanged
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.playmodeStateChanged += () =>
        {
            Debug.Log( "playmodeStateChanged" );
        };
    }
}

Inspector でプロパティが右クリックされた時

  • EditorApplication.contextualPropertyMenu
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorApplication.contextualPropertyMenu += ( menu, property ) =>
        {
            menu.AddItem( new GUIContent( "contextualPropertyMenu" ), false, () =>
            {
                Debug.Log( "contextualPropertyMenu" );
            } );
        };
    }
}

新しいシーンが作成された時

  • EditorSceneManager.newSceneCreated
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorSceneManager.newSceneCreated += OnCreated;
    }

    private static void OnCreated( Scene scene, NewSceneSetup setup, NewSceneMode mode )
    {
        Debug.Log( "newSceneCreated" );
    }
}

シーンを開く直前と直後

  • EditorSceneManager.sceneOpening
  • EditorSceneManager.sceneOpened
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorSceneManager.sceneOpening += OnOpening;
        EditorSceneManager.sceneOpened += OnOpened;
    }

    private static void OnOpening( string path, OpenSceneMode mode )
    {
        Debug.Log( "sceneOpening" );
    }

    private static void OnOpened( Scene scene, OpenSceneMode mode )
    {
        Debug.Log( "sceneOpened" );
    }
}

シーンを閉じる直前と直後

  • EditorSceneManager.sceneClosing
  • EditorSceneManager.sceneClosed
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorSceneManager.sceneClosing += OnClosing;
        EditorSceneManager.sceneClosed += OnClosed;
    }

    private static void OnClosing( Scene scene, bool removingScene )
    {
        Debug.Log( "sceneClosing" );
    }

    private static void OnClosed( Scene scene )
    {
        Debug.Log( "sceneClosed" );
    }
}

シーンを保存する直前と直後

  • EditorSceneManager.sceneSaving
  • EditorSceneManager.sceneSaved
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        EditorSceneManager.sceneSaving += OnSaving;
        EditorSceneManager.sceneSaved += OnSaved;
    }

    private static void OnSaving( Scene scene, string path )
    {
        Debug.Log( "sceneSaving" );
    }

    private static void OnSaved( Scene scene )
    {
        Debug.Log( "sceneSaved" );
    }
}

プレハブのパラメータが変更された時

  • PrefabUtility.prefabInstanceUpdated
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        PrefabUtility.prefabInstanceUpdated += OnUpdated;
    }

    private static void OnUpdated( GameObject instance )
    {
        Debug.Log( "prefabInstanceUpdated" );
    }
}

Undo か Redo された時

  • Undo.undoRedoPerformed
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        Undo.undoRedoPerformed += () =>
        {
            Debug.Log( "undoRedoPerformed" );
        };
    }
}

Undo/Redo の状態が変更された時

  • Undo.willFlushUndoRecord
  • Undo.postprocessModifications
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        Undo.willFlushUndoRecord += () =>
        {
            Debug.Log( "willFlushUndoRecord" );
        };

        Undo.postprocessModifications += OnCallback;
    }

    private static UndoPropertyModification[] OnCallback( UndoPropertyModification[] modifications)
    {
        Debug.Log( "postprocessModifications" );
        return modifications;
    }
}

すべてのアセンブリをリロードする直前と直後

  • AssemblyReloadEvents.beforeAssemblyReload
  • AssemblyReloadEvents.afterAssemblyReload
using UnityEditor;
using UnityEngine;

public static class Example
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        AssemblyReloadEvents.beforeAssemblyReload += () => 
        {
            Debug.Log( "beforeAssemblyReload" );
        };

        AssemblyReloadEvents.afterAssemblyReload += () => 
        {
            Debug.Log( "afterAssemblyReload" );
        };
    }
}

インターフェイス

ビルドターゲットが変更された時

  • IActiveBuildTargetChanged
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;

public class Example : IActiveBuildTargetChanged
{
    public int callbackOrder { get { return 0; } }

    public void OnActiveBuildTargetChanged ( BuildTarget previousTarget,  BuildTarget newTarget )
    {
        Debug.LogFormat( "{0} -> {1}", previousTarget, newTarget );
    }
}

ビルド前とビルド後

  • IPreprocessBuild
  • IPostprocessBuild
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;

public class Example : IPreprocessBuild, IPostprocessBuild
{
    public int callbackOrder { get { return 0; } }

    // ビルド前
    public void OnPreprocessBuild( BuildTarget target, string path )
    {
        Debug.Log( target );
    }

    // ビルド後
    public void OnPostprocessBuild( BuildTarget target, string path )
    {
        Debug.Log( target );
    }
}

ビルド時にシーンが参照された時

  • IProcessScene
using UnityEditor.Build;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Example : IProcessScene
{
    public int callbackOrder { get { return 0; } }

    public void OnProcessScene( Scene scene )
    {
        Debug.Log( scene.name );
    }
}

属性

エディタ起動時やスクリプトのコンパイル完了時

  • InitializeOnLoad
  • InitializeOnLoadMethod
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public static class Example1
{
    static Example1()
    {
        Debug.Log( "InitializeOnLoad" );
    }
}

public static class Example2
{
    [InitializeOnLoadMethod]
    private static void Hoge()
    {
        Debug.Log( "InitializeOnLoadMethod" );
    }
}

アセット名が変更された時

  • EndNameEditAction
using UnityEditor.ProjectWindowCallback;
using UnityEngine;

public class Example : EndNameEditAction
{
    public override void Action( int instanceId, string pathName, string resourceFile )
    {
        Debug.Log( pathName );
    }
}

スクリプトが読み込まれた時

  • DidReloadScripts
using UnityEditor.Callbacks;
using UnityEngine;

public static class Example
{
    [DidReloadScripts( 0 )]
    private static void Hoge()
    {
        Debug.Log( "DidReloadScripts" );
    }
}

アセットが開かれた時

  • OnOpenAsset
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;

public static class Example
{
    [OnOpenAsset( 0 )]
    public static bool OnOpenAsset( int instanceID, int line )
    {
        var obj = EditorUtility.InstanceIDToObject( instanceID );
        Debug.Log( obj.name );
        return false;
    }
}

ビルド後

  • PostProcessBuild
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;

public static class Example
{
    [PostProcessBuild( 0 )]
    public static void OnPostprocessBuild( BuildTarget target, string pathToBuiltProject )
    {
        Debug.Log( pathToBuiltProject );
    }
}

シーン遷移時

  • PostProcessScene
using UnityEditor.Callbacks;
using UnityEngine;

public static class Example
{
    [PostProcessScene( 0 )]
    public static void OnPostProcessScene()
    {
        Debug.Log( "OnPostProcessScene" );
    }
}

関連記事