来自 UnityEditor.InspectorWindow.GetEditorsWithPreviews 的 NullReferenceException
NullReferenceException from UnityEditor.InspectorWindow.GetEditorsWithPreviews
我有一个非常复杂的用于修改模型的 Unity 编辑器脚本。通过在资产文件夹中创建一个新对象,然后在其检查器中为其提供模型、一些修改器并按下应用来使用它。这会修改模型并将创建的对象替换为新的对象预制件。
当按下应用时,方法Apply()
被调用,之后有运行,控制台打印出这个:
NullReferenceException: Object reference not set to an instance of an
object UnityEditor.InspectorWindow.GetEditorsWithPreviews
(UnityEditor.Editor[] editors) (at
C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:515)
UnityEditor.InspectorWindow.DrawPreviewAndLabels () (at
C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:612)
UnityEditor.InspectorWindow.OnGUI () (at
C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:398)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags
invokeAttr, System.Reflection.Binder binder, System.Object[]
parameters, System.Globalization.CultureInfo culture) (at
/Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the
target of an invocation. System.Reflection.MonoMethod.Invoke
(System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder
binder, System.Object[] parameters, System.Globalization.CultureInfo
culture) (at
/Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj,
System.Object[] parameters) (at
/Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
UnityEditor.HostView.Invoke (System.String methodName, System.Object
obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:272)
UnityEditor.HostView.Invoke (System.String methodName) (at
C:/buildslave/unity/build/Editor/Mono/HostView.cs:265)
UnityEditor.HostView.InvokeOnGUI (Rect onGUIPosition) (at
C:/buildslave/unity/build/Editor/Mono/HostView.cs:232)
我发现 2014 年的一个问题有类似的错误,但情况不同,没有答案 here。
我检查了 MattRix's decompiled Unity repo 可能导致异常的原因,即使存储库的版本为 2017.1.0f3 而我使用的是 2017.1.1f1,我想我找到了出现问题的地方。
在 DrawPreviewsAndLabels()
:
IPreviewable[] editorsWithPreviews = this.GetEditorsWithPreviews(this.tracker.activeEditors);
然后
GetEditorsWithPreviews(Editor[] editors){
...
for (int i = 0; i < editors.Length; i++)
{
Editor editor = editors[i];
...
似乎在 Editor editor = editors[i];
行调用了异常。这让我认为 this.tracker.activeEditors
是一个包含 null
元素的列表。这就是我坚持的地方。
什么可能导致此错误,我可以做什么或检查什么来修复此错误?
编辑:有人指出这可能意味着 this.tracker.activeEditors
本身为空。如果是这样的话,我认为异常会发生在 editors.Length
并且或者至少它不应该进入 for 循环。由于行号可能随着 Unity 版本的变化而改变,该代码中的行实际上可能不是异常的原因,但我无法知道。
我无法轻松修复此空指针的问题是它发生在编辑器代码中,而我的代码没有任何调用,我不知道该怎么做才能 this.tracker.activeEditors
或任何导致它的原因正确分配到应有的位置。
我是否必须让一些可能不活跃的东西活跃起来,以便有活跃的编辑,不管那是什么意思?
这是我的Apply()
方法:
private void Apply(List<Mesh> meshes, List<Material[]> materials, Chamferer chamferer)
{
GameObject newObject = Instantiate(chamferer.gameObject);
Object targetPrefab = PrefabUtility.GetPrefabObject(chamferer);
string name = chamferer.source.name;
//Delete previous meshes
MeshFilter[] filters = newObject.transform.GetComponentsInChildren<MeshFilter>();
for (int i = 0; i < filters.Length; i++)
{
filters[i].transform.SetParent(null);
GameObject.DestroyImmediate(filters[i].gameObject);
}
string prefabPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(targetPrefab));
Mesh prev = null;
//Add new meshes
for (int i = 0; i < meshes.Count; i++)
{
Mesh mesh = meshes[i];
Mesh newMesh = EdgeChamfer.AddChamfer(mesh, chamferer.scale);
GameObject obj = new GameObject(mesh.name);
obj.transform.SetParent(newObject.transform);
MeshFilter mf = obj.AddComponent<MeshFilter>();
MeshRenderer mr = obj.AddComponent<MeshRenderer>();
mf.sharedMesh = newMesh;
mr.sharedMaterials = materials[i];
//Adds mesh under prefab
if (i == 0)
{
AssetDatabase.CreateAsset(newMesh, prefabPath + "/" + name + ".asset");
prev = newMesh;
}
else
{
AssetDatabase.AddObjectToAsset(newMesh, prev);
prev = newMesh;
}
}
AssetDatabase.SaveAssets();
GameObject newPrefab = PrefabUtility.ReplacePrefab(newObject, targetPrefab);
//Renames the object accordingly
string renamingerr = AssetDatabase.RenameAsset(prefabPath + "/" + newPrefab.name + ".prefab", "Chamfered" + name);
if (renamingerr != "")
{
Debug.Log(renamingerr);
}
Selection.activeObject = newPrefab;
EditorGUIUtility.PingObject(newPrefab);
GameObject.DestroyImmediate(newObject);
}
完整 GetEditorsWithPreviews()
来自 MattRix's repo:
public IPreviewable[] GetEditorsWithPreviews(Editor[] editors)
{
IList<IPreviewable> list = new List<IPreviewable>();
int num = -1;
for (int i = 0; i < editors.Length; i++)
{
Editor editor = editors[i];
num++;
if (!(editor.target == null))
{
if (!EditorUtility.IsPersistent(editor.target) || !(AssetDatabase.GetAssetPath(editor.target) != AssetDatabase.GetAssetPath(editors[0].target)))
{
if (EditorUtility.IsPersistent(editors[0].target) || !EditorUtility.IsPersistent(editor.target))
{
if (!this.ShouldCullEditor(editors, num))
{
if (!(editors[0] is AssetImporterEditor) || editor is AssetImporterEditor)
{
if (editor.HasPreviewGUI())
{
list.Add(editor);
}
}
}
}
}
}
}
foreach (IPreviewable current in this.m_Previews)
{
if (current.HasPreviewGUI())
{
list.Add(current);
}
}
return list.ToArray<IPreviewable>();
}
似乎 OnInspectorGUI()
在替换对象后尝试执行某些操作时可能会出现错误。
如果不替换预制件而是创建新的预制件,则不会出现该错误。
所以在代码中,通过替换
解决了问题
GameObject newPrefab = PrefabUtility.ReplacePrefab(newObject, targetPrefab);
在“应用()”中与
GameObject newPrefab = PrefabUtility.CreatePrefab(prefabPath + "/" + name + ".prefab", newObject);
我有一个非常复杂的用于修改模型的 Unity 编辑器脚本。通过在资产文件夹中创建一个新对象,然后在其检查器中为其提供模型、一些修改器并按下应用来使用它。这会修改模型并将创建的对象替换为新的对象预制件。
当按下应用时,方法Apply()
被调用,之后有运行,控制台打印出这个:
NullReferenceException: Object reference not set to an instance of an object UnityEditor.InspectorWindow.GetEditorsWithPreviews (UnityEditor.Editor[] editors) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:515) UnityEditor.InspectorWindow.DrawPreviewAndLabels () (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:612) UnityEditor.InspectorWindow.OnGUI () (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:398) System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222) Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation. System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232) System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115) UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:272) UnityEditor.HostView.Invoke (System.String methodName) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:265) UnityEditor.HostView.InvokeOnGUI (Rect onGUIPosition) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:232)
我发现 2014 年的一个问题有类似的错误,但情况不同,没有答案 here。
我检查了 MattRix's decompiled Unity repo 可能导致异常的原因,即使存储库的版本为 2017.1.0f3 而我使用的是 2017.1.1f1,我想我找到了出现问题的地方。
在 DrawPreviewsAndLabels()
:
IPreviewable[] editorsWithPreviews = this.GetEditorsWithPreviews(this.tracker.activeEditors);
然后
GetEditorsWithPreviews(Editor[] editors){
...
for (int i = 0; i < editors.Length; i++)
{
Editor editor = editors[i];
...
似乎在 Editor editor = editors[i];
行调用了异常。这让我认为 this.tracker.activeEditors
是一个包含 null
元素的列表。这就是我坚持的地方。
什么可能导致此错误,我可以做什么或检查什么来修复此错误?
编辑:有人指出这可能意味着 this.tracker.activeEditors
本身为空。如果是这样的话,我认为异常会发生在 editors.Length
并且或者至少它不应该进入 for 循环。由于行号可能随着 Unity 版本的变化而改变,该代码中的行实际上可能不是异常的原因,但我无法知道。
我无法轻松修复此空指针的问题是它发生在编辑器代码中,而我的代码没有任何调用,我不知道该怎么做才能 this.tracker.activeEditors
或任何导致它的原因正确分配到应有的位置。
我是否必须让一些可能不活跃的东西活跃起来,以便有活跃的编辑,不管那是什么意思?
这是我的Apply()
方法:
private void Apply(List<Mesh> meshes, List<Material[]> materials, Chamferer chamferer)
{
GameObject newObject = Instantiate(chamferer.gameObject);
Object targetPrefab = PrefabUtility.GetPrefabObject(chamferer);
string name = chamferer.source.name;
//Delete previous meshes
MeshFilter[] filters = newObject.transform.GetComponentsInChildren<MeshFilter>();
for (int i = 0; i < filters.Length; i++)
{
filters[i].transform.SetParent(null);
GameObject.DestroyImmediate(filters[i].gameObject);
}
string prefabPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(targetPrefab));
Mesh prev = null;
//Add new meshes
for (int i = 0; i < meshes.Count; i++)
{
Mesh mesh = meshes[i];
Mesh newMesh = EdgeChamfer.AddChamfer(mesh, chamferer.scale);
GameObject obj = new GameObject(mesh.name);
obj.transform.SetParent(newObject.transform);
MeshFilter mf = obj.AddComponent<MeshFilter>();
MeshRenderer mr = obj.AddComponent<MeshRenderer>();
mf.sharedMesh = newMesh;
mr.sharedMaterials = materials[i];
//Adds mesh under prefab
if (i == 0)
{
AssetDatabase.CreateAsset(newMesh, prefabPath + "/" + name + ".asset");
prev = newMesh;
}
else
{
AssetDatabase.AddObjectToAsset(newMesh, prev);
prev = newMesh;
}
}
AssetDatabase.SaveAssets();
GameObject newPrefab = PrefabUtility.ReplacePrefab(newObject, targetPrefab);
//Renames the object accordingly
string renamingerr = AssetDatabase.RenameAsset(prefabPath + "/" + newPrefab.name + ".prefab", "Chamfered" + name);
if (renamingerr != "")
{
Debug.Log(renamingerr);
}
Selection.activeObject = newPrefab;
EditorGUIUtility.PingObject(newPrefab);
GameObject.DestroyImmediate(newObject);
}
完整 GetEditorsWithPreviews()
来自 MattRix's repo:
public IPreviewable[] GetEditorsWithPreviews(Editor[] editors)
{
IList<IPreviewable> list = new List<IPreviewable>();
int num = -1;
for (int i = 0; i < editors.Length; i++)
{
Editor editor = editors[i];
num++;
if (!(editor.target == null))
{
if (!EditorUtility.IsPersistent(editor.target) || !(AssetDatabase.GetAssetPath(editor.target) != AssetDatabase.GetAssetPath(editors[0].target)))
{
if (EditorUtility.IsPersistent(editors[0].target) || !EditorUtility.IsPersistent(editor.target))
{
if (!this.ShouldCullEditor(editors, num))
{
if (!(editors[0] is AssetImporterEditor) || editor is AssetImporterEditor)
{
if (editor.HasPreviewGUI())
{
list.Add(editor);
}
}
}
}
}
}
}
foreach (IPreviewable current in this.m_Previews)
{
if (current.HasPreviewGUI())
{
list.Add(current);
}
}
return list.ToArray<IPreviewable>();
}
似乎 OnInspectorGUI()
在替换对象后尝试执行某些操作时可能会出现错误。
如果不替换预制件而是创建新的预制件,则不会出现该错误。 所以在代码中,通过替换
解决了问题GameObject newPrefab = PrefabUtility.ReplacePrefab(newObject, targetPrefab);
在“应用()”中与
GameObject newPrefab = PrefabUtility.CreatePrefab(prefabPath + "/" + name + ".prefab", newObject);