using System; using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; public class FindMissingPrefabs : EditorWindow { [MenuItem("Tools/Find Missing Prefabs")] static void Init() { GetWindow("Find Missing Prefabs").Show(); } private List missingPrefabs = new List(); void OnGUI() { if (GUILayout.Button("Find Missing Prefabs in Scene")) { FindMissing(); } if (missingPrefabs.Count > 0) { GUILayout.Label("Missing Prefabs Found:", EditorStyles.boldLabel); foreach (var obj in missingPrefabs.Take(32)) { if (GUILayout.Button(obj.name)) { Selection.activeGameObject = obj; AutoFix(obj); } } } else { GUILayout.Label("No missing prefabs found."); } } void FindMissing() { missingPrefabs.Clear(); GameObject[] allObjects = GameObject.FindObjectsOfType(); foreach (GameObject obj in allObjects) { PrefabAssetType prefabType = PrefabUtility.GetPrefabAssetType(obj); if (prefabType == PrefabAssetType.MissingAsset) { if (PrefabUtility.IsAnyPrefabInstanceRoot(obj) is false)continue; AutoFix(obj); missingPrefabs.Add(obj); } } } private bool AutoFix(GameObject obj) { // 解析 name(括号前的部分) Match nameMatch = Regex.Match(obj.name, @"^(.+?)\s*\("); var name = nameMatch.Success ? nameMatch.Groups[1].Value : "N/A"; if (nameMatch.Success is false) { Debug.LogWarning("未能解析到Name"); return false; } // 解析 guid Match guidMatch = Regex.Match(obj.name, @"guid:\s*([a-f0-9]{32})"); if (guidMatch.Success is false) { Debug.LogWarning("未能解析到GUID"); return false; } var guid = guidMatch.Success ? guidMatch.Groups[1].Value : "N/A"; var searchStr =name+ @" t:prefab"; var searchPrefabs = AssetDatabase.FindAssets(searchStr); Debug.Log($"找到:{name}有关的{searchStr}结果:\n"+string.Join("\n",searchPrefabs)); var errorGuid = string.Empty; switch (searchPrefabs.Length) { case > 1: { try { foreach (var searchId in searchPrefabs) { var prefabName = AssetDatabase.GUIDToAssetPath(searchId); var prefab = AssetDatabase.LoadAssetAtPath(prefabName); if (prefab.name == name) { errorGuid = searchId; throw new OperationCanceledException(); } } Debug.LogWarning($"找到的结果有:{searchPrefabs.Length},无法自动修复"); return false; } catch (OperationCanceledException) { } } break; case 1: { errorGuid = searchPrefabs[0]; } break; case 0: { Debug.Log("未找到"); } break; } var path = AssetDatabase.GUIDToAssetPath(errorGuid); var metaPath = path + ".meta"; metaPath = Path.Combine(Environment.CurrentDirectory, metaPath); if (File.Exists(metaPath) is false) { Debug.Log($"Meta路径未找到:{{metaPath}}"); return false; } var str = File.ReadAllText(metaPath); str = str.Replace(searchPrefabs[0], guid); File.WriteAllText(metaPath, str); Debug.Log($"{name}已修复"); return true; } }