我有一个显示对象列表的自定义窗口。每个对象都有一个自定义检查器编辑器。
可以在自定义窗口中显示自定义检查器吗?
答案 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);
}