【UnityEditor】EditorWindowにShowButtonメソッドを作ってはいけない

環境

Windows 10
Unity 5.6.1f1

事の発端

ある時、以下のようなEditorWindowクラスを作ったところエラーが出てしまいました。

TestEditorWindow.cs
using UnityEngine;
using UnityEditor;

public class TestEditorWindow : EditorWindow
{
    [MenuItem("Tools/TestEditorWindow")]
    static public void Open()
    {
        GetWindow<TestEditorWindow>();
    }

    void ShowButton()
    {
    }
}

image.png

なんだこれは....

エラーの意味

MSDN(https://msdn.microsoft.com/ja-jp/library/4k9x6bc0(v=vs.110).aspx) によると

parameters 配列に正しい数の引数がありません。

という意味のエラーだそうです。(TargetParameterCountException)

エラーの発生個所

スタックトレースの中に

UnityEditor.HostView.ShowGenericMenu () (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:350)

とあるので、HostView.cs の中でエラーが出ているようです。

エラー発生個所のコードを見てみる

HostView.csはDLLの中へ隠蔽されているので
下記リポジトリからUnity内部のソースコードを読んでみます。

https://github.com/MattRix/UnityDecompiled

HostView.csの中身

Unity5.6.0f3デコンパイルコードのHostView.csを読んでみるとShowButtonメソッドをリフレクション経由で呼び出している箇所がありました。

HostView.csの350~370行あたりのソースコード
protected void ShowGenericMenu()
{
    GUIStyle gUIStyle = "PaneOptions";
    Rect rect = new Rect(base.position.width - gUIStyle.fixedWidth - 4f, Mathf.Floor((float)(this.background.margin.top + 20) - gUIStyle.fixedHeight), gUIStyle.fixedWidth, gUIStyle.fixedHeight);
    if (EditorGUI.DropdownButton(rect, GUIContent.none, FocusType.Passive, "PaneOptions"))
    {
        this.PopupGenericMenu(this.m_ActualView, rect);
    }
    MethodInfo paneMethod = this.GetPaneMethod("ShowButton", this.m_ActualView);
    if (paneMethod != null)
    {
        object[] parameters = new object[]
        {
            new Rect(base.position.width - gUIStyle.fixedWidth - 20f, Mathf.Floor((float)(this.background.margin.top + 4)), 16f, 16f)
        };
        paneMethod.Invoke(this.m_ActualView, parameters);
    }
}
HostView.csの170~190行あたりのソースコード
private MethodInfo GetPaneMethod(string methodName)
{
    return this.GetPaneMethod(methodName, this.m_ActualView);
}
private MethodInfo GetPaneMethod(string methodName, object obj)
{
    MethodInfo result;
    if (obj == null)
    {
        result = null;
    }
    else
    {
        for (Type type = obj.GetType(); type != null; type = type.BaseType)
        {
            MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

引数としてRect型変数を指定してリフレクション経由でShowButtonメソッドを呼んでいるようです。

どうやら先ほどのエラーは、EditorWindow内に引数なしShowButtonメソッドを定義したことによって発生してしまっていたようです。

試しにShowButton(Rect r)を定義してみる

以下のようなEditorWindowクラスを作成してウィンドウを開いてみます。

TestEditorWindow.cs
using UnityEngine;
using UnityEditor;

public class TestEditorWindow : EditorWindow
{
    [MenuItem("Tools/TestEditorWindow")]
    static public void Open()
    {
        GetWindow<TestEditorWindow>();
    }

    void ShowButton(Rect r)
    {
        Debug.Log("called ShowButton");
    }
}

image.png

ShowButtonメソッドが呼ばれていることが確認できました。(完

まとめ

EditorWindowクラスにShowButtonメソッドを作ると、Unity側から勝手に呼ばれてしまうのでShowButtonメソッドは作ってはいけません