自定义窗口上的Unity自定义检查器

时间:2013-04-17 08:15:59

标签: unity3d

我有一个显示对象列表的自定义窗口。每个对象都有一个自定义检查器编辑器。

可以在自定义窗口中显示自定义检查器吗?

2 个答案:

答案 0 :(得分:6)

你不能强迫Unity3D在检查员窗口以外的地方绘制自定义检查器。

您可以使用Editor.CreateEditor方法手动设置Editor。 由于您正在显示自定义检查器,因此应该可以从Window.OnGUI方法内手动实例化它,并使用编辑器的公共OnInspectorGUI方法在窗口内绘制编辑器。

例如,如果您已将名为CustomScript的脚本附加到GameObject并且有一个名为Editor的相关CustomScriptEditor,则假设您已选择GameObject从层次结构中,此代码可视化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();            
        }

    }
}

答案 1 :(得分:3)

截至目前,该问题是诸如“编辑器窗口内的统一检查器”之类的查询的Google最佳搜索结果,因此,我正在制作一个亡灵邮报,以分享我在数小时的沮丧中学到的非常重要的信息:

我正在构建一个使用EditorWindow内的自定义检查器的Editor工具,并且使用了与Heisenbug完全相同的方法。有时在使用该工具时,我的控制台会受到数百个神秘的null引用异常的轰炸。重新启动Unity将使它们消失,但它们不可避免地会返回。我终于能够将问题追溯到“ Editor.CreateEditor”,这是我从困难的中学到的教训:

您需要手动销毁从Editor.CreateEditor创建的所有检查器!

通常,当选择了相关对象时,Unity将实例化检查器,并在取消选择/删除对象等后自动销毁该实例。但是通过Editor.CreateEditor创建的检查器将永远不会被销毁,并且在被检查的对象被销毁后很长时间仍会在内存中徘徊。

您可以通过将以下代码添加到自定义检查器中来证明这一点:

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

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

通常使用检查器,当检查器实例被创建然后销毁时,您将始终成对看到这些消息。但是,尝试从您的EditorWindow类实例化一些检查器,您将仅看到“启用”消息。

我了解到,只要重新编译脚本,Unity就会调用OnEnable()。尝试一下,您将看到控制台中充满了从未清除过的所有检查器实例的“启用”消息。这些实例将在其检查的对象被销毁后留下很长的时间,并且OnEnable()中的任何初始化代码都会引人注目地破坏,并引发大量的神秘异常。

我的解决方案如下(该代码将在您的EditorWindow类中显示):

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);
}