Unity Custom Inspector on Custom Window

2020-07-09 07:00发布

I have a custom window that show a list of objects. Each of this objects has a custom inspector editor.

Is possible to show custom inspector inside the custom window?

标签: unity3d
2条回答
beautiful°
2楼-- · 2020-07-09 07:16

As of right now, this question is a top google result for queries such as "Unity inspector inside editor window" so I'm making a necropost to share some very important information I learned through hours of frustration:

I'm building an Editor tool which makes use of custom inspectors inside of an EditorWindow, and I used the exact same method as Heisenbug. Occasionally while working on the tool my console would be bombarded with hundreds of mysterious null reference exceptions. Restarting Unity would make them go away but they would inevitably return. I was finally able to trace the problem to "Editor.CreateEditor", here is the lesson I learned the hard way:

You need to manually destroy any inspectors created from Editor.CreateEditor!

Normally Unity will instantiate an inspector when the relevant object is selected, and automatically destroy that instance as soon as the object is deselected/deleted/etc. But an inspector created via Editor.CreateEditor will never be destroyed and will linger somewhere in memory long after the object it was inspecting has been destroyed.

You can prove this by adding the following code to your custom inspector:

void OnEnable()
{
    Debug.Log("on enable " + this.GetInstanceID());
}

void OnDisable()
{
    Debug.Log("on disable " + this.GetInstanceID());
}

Using the inspector normally, you will always see these messages in pairs as instances of the inspector get created and then destroyed. But try instantiating a few inspectors from your EditorWindow class and you will only see the "on enable" messages.

I learned that Unity calls OnEnable() whenever scripts are recompiled. Try it and you'll see your console fill up with "on enable" messages from all the inspector instances that were never cleaned up. These instances will linger long after the objects they were inspecting have been destroyed, and any initialization code in OnEnable() will break spectacularly throwing an avalanche of mysterious exceptions.

My solution looks something like this (this code would go in your EditorWindow class):

Editor embeddedInspector;

...

// a helper method that destroys the current inspector instance before creating a new one
// use this in place of "Editor.CreateEditor"
void RecycleInspector(Object target)
{
    if (embeddedInspector != null) DestroyImmediate(embeddedInspector);
    embeddedInspector = Editor.CreateEditor(target);
}

...

// clean up the inspector instance when the EditorWindow itself is destroyed
void OnDisable()
{
    if (embeddedInspector != null) DestroyImmediate(embeddedInspector);
}
查看更多
爷、活的狠高调
3楼-- · 2020-07-09 07:18

You can't force Unity3D to draw your custom inspector somewhere else than inspector window.

Btw you can manually instatiate an Editor using Editor.CreateEditor method. Since you are displaying a custom inspector, than it should be possible to instantiate it manually from inside Window.OnGUI method, and use the public OnInspectorGUI method of the editor to draw the editor inside your window.

For example, if you have attached a script called CustomScript to a GameObject and have a related Editor called CustomScriptEditor, supposing you have selected the GameObject from the hierarchy, this code visualize the custom inspector inside an EditorWindow:

using UnityEditor;
using UnityEngine;


public class TestWindow : EditorWindow
{

    [MenuItem ("Window/Editor Window Test")]
    static void Init () 
    {
        // Get existing open window or if none, make a new one:
        TestWindow window = (TestWindow)EditorWindow.GetWindow (typeof (TestWindow));
    }

    void OnGUI () {

        GameObject sel = Selection.activeGameObject;

        CustomScript targetComp = sel.GetComponent<CustomScript>();

        if (targetComp != null)
        {
            var editor = Editor.CreateEditor(targetComp);
            editor.OnInspectorGUI();            
        }

    }
}
查看更多
登录 后发表回答