我有一个显示对象列表的自定义窗口。每个对象都有一个自定义检查器编辑器。
是否可以在自定义窗口中显示自定义检查器?
您不能强制Unity3D
在检查器窗口以外的其他地方绘制自定义检查器。
顺便说一句,您可以手动实例化Editor
using Editor.CreateEditor方法。由于您正在显示自定义检查器,因此应该可以从内部Window.OnGUI
方法手动实例化它,并使用编辑器的公共OnInspectorGUI
方法在窗口内绘制编辑器。
例如,如果您附加了一个名为 a 的脚本CustomScript
并GameObject
有一个相关的Editor
名为CustomScriptEditor
,假设您GameObject
已从层次结构中选择了 ,则此代码将自定义检查器可视化为 a 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();
}
}
}
截至目前,这个问题是诸如“编辑器窗口内的 Unity 检查器”之类的查询的顶级谷歌结果,所以我正在制作一个 necropost 来分享一些我在数小时的挫折中学到的非常重要的信息:
我正在构建一个编辑器工具,该工具在 EditorWindow 内使用自定义检查器,并且我使用了与 Heisenbug 完全相同的方法。有时在使用该工具时,我的控制台会被数百个神秘的空引用异常轰炸。重新启动 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);
}