RefTool.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor;
  5. using UnityEngine;
  6. public class RefTool : EditorWindow
  7. {
  8. [MenuItem("Tools/检查/检查MissingReference资源")]
  9. public static void FindMissing()
  10. {
  11. Find();
  12. foreach (var item in refPaths)
  13. {
  14. Debug.Log(item);
  15. }
  16. }
  17. private enum PrefabErrorType
  18. {
  19. None = 0,
  20. Waring = 1,
  21. Error = 2,
  22. }
  23. private static Dictionary<UnityEngine.Object, List<UnityEngine.Object>> prefabs = new Dictionary<UnityEngine.Object, List<UnityEngine.Object>>();
  24. private static Dictionary<UnityEngine.Object, string> refPaths = new Dictionary<UnityEngine.Object, string>();
  25. private static void Find()
  26. {
  27. prefabs.Clear();
  28. string[] allassetpaths = AssetDatabase.GetAllAssetPaths();
  29. EditorUtility.DisplayProgressBar("统计", "统计所有的Prefab", 0);
  30. //获取所有资源路径
  31. var gos = allassetpaths
  32. .Where(a => a.EndsWith("prefab"))//筛选 是以prefab为后缀的 预设体资源
  33. .Select(a => AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(a));//加载这个预设体
  34. //gos拿到的是所有加载好的预设体
  35. int index = 0, count = gos.Count();
  36. foreach (var item in gos)
  37. {
  38. GameObject go = item as GameObject;
  39. if (go)
  40. {
  41. PrefabErrorType prefabErrorType = PrefabErrorType.None;
  42. string path = AssetDatabase.GetAssetPath(go);
  43. EditorUtility.DisplayProgressBar("检查", path, (float)index / count);
  44. Component[] cps = go.GetComponentsInChildren<Component>(true);//获取这个物体身上所有的组件
  45. foreach (var cp in cps)//遍历每一个组件
  46. {
  47. if (!cp)
  48. {
  49. if (!prefabs.ContainsKey(go))
  50. {
  51. prefabs.Add(go, new List<UnityEngine.Object>() { cp });
  52. }
  53. else
  54. {
  55. prefabs[go].Add(cp);
  56. }
  57. continue;
  58. }
  59. SerializedObject so = new SerializedObject(cp);//生成一个组件对应的S俄日阿里则对Object对象 用于遍历这个组件的所有属性
  60. var iter = so.GetIterator();//拿到迭代器
  61. while (iter.NextVisible(true))//如果有下一个属性
  62. { //如果这个属性类型是引用类型的
  63. if (iter.propertyType == SerializedPropertyType.ObjectReference)
  64. { //引用对象是null 并且 引用ID不是0 说明丢失了引用
  65. if (iter.objectReferenceValue == null && iter.objectReferenceInstanceIDValue != 0)
  66. {
  67. if (!refPaths.ContainsKey(cp)) refPaths.Add(cp, iter.propertyPath);
  68. else refPaths[cp] += " | " + iter.propertyPath;
  69. if (prefabs.ContainsKey(go))
  70. {
  71. if (!prefabs[go].Contains(cp)) prefabs[go].Add(cp);
  72. }
  73. else
  74. {
  75. prefabs.Add(go, new List<UnityEngine.Object>() { cp });
  76. }
  77. }
  78. }
  79. }
  80. if ((cp is Transform))
  81. {
  82. if (prefabErrorType != PrefabErrorType.Error)
  83. {
  84. if (PrefabUtility.IsPartOfPrefabInstance(cp))
  85. {
  86. if (!PrefabUtility.GetCorrespondingObjectFromSource(cp))
  87. {
  88. if (cp.name == "Missing Prefab (Dummy)")
  89. {
  90. prefabErrorType = PrefabErrorType.Error;
  91. }
  92. if (prefabErrorType == PrefabErrorType.None)
  93. {
  94. prefabErrorType = PrefabErrorType.Waring;
  95. }
  96. }
  97. }
  98. }
  99. }
  100. }
  101. if (prefabErrorType == PrefabErrorType.Error)
  102. {
  103. Debug.LogError(path + " has Missing Prefab (Dummy) !!!", go);
  104. }
  105. else if (prefabErrorType == PrefabErrorType.Waring)
  106. {
  107. Debug.LogWarning(path + " has Missing Prefab !!!", go);
  108. }
  109. EditorUtility.DisplayProgressBar("检查", path, (float)(index + 1) / count);
  110. }
  111. index = index + 1;
  112. }
  113. EditorUtility.ClearProgressBar();
  114. EditorUtility.DisplayDialog("", "就绪", "OK");
  115. }
  116. }