BITFALL/Assets/_Scripts/GuidFix.cs

149 lines
4.2 KiB
C#
Raw Normal View History

2025-03-14 19:46:24 +08:00
using System;
2025-03-14 19:05:51 +08:00
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
2025-03-14 19:46:24 +08:00
using System.IO;
2025-03-14 19:05:51 +08:00
using System.Linq;
2025-03-14 19:46:24 +08:00
using System.Text.RegularExpressions;
2025-03-14 19:05:51 +08:00
public class FindMissingPrefabs : EditorWindow
{
[MenuItem("Tools/Find Missing Prefabs")]
static void Init()
{
GetWindow<FindMissingPrefabs>("Find Missing Prefabs").Show();
}
private List<GameObject> missingPrefabs = new List<GameObject>();
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;
2025-03-14 19:46:24 +08:00
AutoFix(obj);
2025-03-14 19:05:51 +08:00
}
}
}
else
{
GUILayout.Label("No missing prefabs found.");
}
}
void FindMissing()
{
missingPrefabs.Clear();
GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>();
foreach (GameObject obj in allObjects)
{
PrefabAssetType prefabType = PrefabUtility.GetPrefabAssetType(obj);
if (prefabType == PrefabAssetType.MissingAsset)
{
2025-03-14 19:46:24 +08:00
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<GameObject>(prefabName);
if (prefab.name == name)
{
errorGuid = searchId;
throw new OperationCanceledException();
}
}
Debug.LogWarning($"找到的结果有:{searchPrefabs.Length},无法自动修复");
return false;
}
catch (OperationCanceledException)
{
}
}
break;
case 1:
{
errorGuid = searchPrefabs[0];
2025-03-14 19:05:51 +08:00
}
2025-03-14 19:46:24 +08:00
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;
2025-03-14 19:05:51 +08:00
}
2025-03-14 19:46:24 +08:00
var str = File.ReadAllText(metaPath);
str = str.Replace(searchPrefabs[0], guid);
File.WriteAllText(metaPath, str);
Debug.Log($"{name}已修复");
return true;
2025-03-14 19:05:51 +08:00
}
}