介绍
Unity 2018 中如果 Prefab 中存在 Missing Component 会导致无法保存 Prefab,必须修正脚本引用才可以保存。
1
2
3
|
The Prefab file contains an invalid script. Applying
is not possible. Enter Prefab Mode and remove or
recover the script.
|
在缺失脚本的组件上可以看到以下提示:
1
2
3
|
The associated script can not be loaded.
Please fix any compile errors
and assign a valid script.
|
网上搜索到的查找丢失脚本的代码大部分都是找到存在丢失脚本的 Prefab,而无法找到 Prefab 中是哪一个结点上的脚本组件丢失了。
这个项目就是一个写得不错的项目,而且一直在维护。
推荐使用这个工具找到项目内所有丢失脚本的 Prefab,再配合下面的工具找到丢失脚本的结点。
环境
使用
只需要将以下代码保存到 Editor
目录即可使用,执行 Tools/Find Missing References
后会在 Console 中列出所有存在丢失脚本的结点,点击后可以在 Hierarchy
视图跳转到对应的结点上。
注意:工具会同时找到所有丢失引用的组件。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEngine;
public static class FindMissingReferences
{
[MenuItem("Tools/Find Missing References")]
public static void Find()
{
var go = Selection.activeGameObject;
if (go == null)
{
Debug.LogError("Please select GameObject first");
return;
}
var prefabType = PrefabUtility.GetPrefabAssetType(go);
if (prefabType == PrefabAssetType.Regular || prefabType == PrefabAssetType.Variant)
{
AssetDatabase.OpenAsset(go);
EditorApplication.ExecuteMenuItem("Window/General/Hierarchy");
go = Selection.activeGameObject;
}
var queue = new Queue<Transform>();
queue.Enqueue(go.transform);
while (queue.Count > 0)
{
var transform = queue.Dequeue();
FindMissingReferencesInTransform(transform);
for (int i = 0; i < transform.childCount; i++)
{
queue.Enqueue(transform.GetChild(i));
}
}
}
private static void FindMissingReferencesInTransform(Transform transform)
{
var components = transform.GetComponents<Component>();
foreach (var component in components)
{
if (component == null)
{
ShowMissingScript(transform);
}
else
{
var so = new SerializedObject(component);
var sp = so.GetIterator();
while (sp.NextVisible(true))
{
if (sp.propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
if (sp.objectReferenceValue == null && sp.objectReferenceInstanceIDValue != 0)
{
ShowMissingReference(transform, component, sp.name);
}
}
}
}
}
private static void ShowMissingScript(Transform transform)
{
Debug.LogError("Missing script found on: " + GetGameObjectPath(transform), transform.gameObject);
}
private static void ShowMissingReference(Transform transform, Component component, string propertyName)
{
string message = string.Format("Missing reference found in: {0}, Component: {1}, Property : {2}",
GetGameObjectPath(transform), component, propertyName);
Debug.LogWarning(message, transform.gameObject);
}
private static string GetGameObjectPath(Transform transform)
{
var result = new StringBuilder(transform.name);
while (transform.parent != null)
{
transform = transform.parent;
result.Insert(0, transform.name + "/");
}
return result.ToString();
}
}
|