batch delete achieve unity on Prefab Miss script components

Thanks: https://www.cnblogs.com/AaronBlogs/p/7976054.html 

My unity versions: unity2017.2.0p4

This article will be recording my personal practice, in some cases it may not be taken into account. With the unity of the upgrade version, there may be ready api can directly implement (like unity2019 in GameObjectUtility.RemoveMonoBehavioursWithMissingScript (go), there is no specific test)

Goals:

     To        , and is not restored in the case of a subsequent operation of FIG.

First explain, in both cases miss script:

   In Inpsector panel looks like, open the corresponding prefab files, continue to look at the inherent differences down.

After execution tool change prefab document became the following structure:

Paste the code below:

  1 using System;
  2 using System.IO;
  3 using System.Collections;
  4 using System.Collections.Generic;
  5 using UnityEngine;
  6 using UnityEditor;
  7 using System.Text.RegularExpressions;
  8 
  9 namespace LgsProject
 10 {
 11     public partial class LgsTools_Optimization
 12     {
 13         [MenuItem("LgsTools/智能检测/Remove Missing-MonoBehavior Component")]
 14         static public void RemoveMissComponent()
 15         {
 16             string fullPath = Application.dataPath + "/Art/Prefabs";
 17             fullPath = fullPath.Replace("/", @"\");
 18             List<string> pathList = GetAssetsPath(fullPath, "*.prefab", SearchOption.AllDirectories);
 19             int counter = 0;
 20             for (int i = 0, iMax = pathList.Count; i < iMax; i++)
 21             {
 22                 EditorUtility.DisplayProgressBar("处理进度", string.Format("{0}/{1}", i + 1, iMax), (i + 1f) / iMax);
 23                 if (CheckMissMonoBehavior(pathList[i]))
 24                     ++counter;
 25             }
 26             EditorUtility.ClearProgressBar();
 27             EditorUtility.DisplayDialog("处理结果", "完成修改,修改数量 : " + counter, "确定");
 28             AssetDatabase.Refresh();
 29         }
 30 
 31         /// <summary>
 32         /// 获取某种资源的路径
 33         /// </summary>
 34         /// <param name="fullPath">例如 : Application.dataPath + "/Art/Prefabs" </param>
 35         /// <param name="filter">例如 : *.prefab</param>
 36         /// <param name="searchOption">目录的搜索方式</param>
 37         /// <returns></returns>
 38         static List<string> GetAssetsPath(string fullPath, string filter, SearchOption searchOption)
 39         {
 40             List<string> pathList = new List<string>();
 41             string[] files = Directory.GetFiles(fullPath, filter, searchOption);
 42             for (int i = 0; i < files.Length; i++)
 43             {
 44                 string path = files[i];
 45                 path = "Assets" + path.Substring(Application.dataPath.Length, path.Length - Application.dataPath.Length);
 46                 pathList.Add(path);
 47             }
 48 
 49             return pathList;
 50         }
 51 
 52         /// <summary>  
 53         /// 删除一个Prefab上的空脚本  
 54         /// </summary>  
 55         /// <param name="path">prefab路径 例Assets/Resources/FriendInfo.prefab</param>  
 56         static bool CheckMissMonoBehavior(string path)
 57         {
 58             bool isNull = false;
 59             string s = File.ReadAllText(path);
 60             Regex regBlock = new Regex("MonoBehaviour");
 61             // 以"---"划分组件  
 62             string[] strArray = s.Split(new string[] { "---" }, StringSplitOptions.RemoveEmptyEntries);
 63             for (int i = 0; i < strArray.Length; i++)
 64             {
 65                 string blockStr = strArray[i];
 66                 if (regBlock.IsMatch(blockStr))
 67                 {
 68                     // 模块是 MonoBehavior  
 69                     Match guidMatch = Regex.Match(blockStr, "m_Script: {fileID: (.*), guid: (?<GuidValue>.*?), type:");
 70                     Match guidMatch_1 = Regex.Match(blockStr, "m_Script: {fileID: (.*)");
 71 
 72                     if (guidMatch.Success || guidMatch_1.Success)
 73                     {
 74                         // 获取 MonoBehavior的guid  
 75                         string guid = guidMatch.Groups["GuidValue"].Value;
 76                         Debug.Log("Guid:" + guid);
 77                         string tempPath = AssetDatabase.GUIDToAssetPath(guid);
 78 
 79                         if (string.IsNullOrEmpty(tempPath) || !File.Exists(tempPath))
 80                         {
 81                             isNull = true;
 82                             // 删除操作  
 83                             // 删除MonoScript  
 84                             s = s.Replace("---" + blockStr, "");
 85                             Match idMatch = Regex.Match(blockStr, "!u!(.*) &(?<idValue>.*?)\n");
 86                             if (idMatch.Success)
 87                             {
 88                                 // 获取 MonoBehavior的guid  
 89                                 string id = idMatch.Groups["idValue"].Value;
 90                                 // 删除MonoScript的引用
 91                                 Regex quote = new Regex("  - (.*): {fileID: " + id + "}\n");
 92                                 s = quote.Replace(s, "");
 93                             }
 94                         }
 95                     }
 96                 }
 97             }
 98             if (isNull)
 99             {
100                 // 有空脚本 写回prefab  
101                 File.WriteAllText(path, s);
102             }
103             return isNull;
104         }
105     }
106 }

另外,在实践的过程中遇到了一个报错,顺便记录一下:

CheckConsistency: GameObject does not reference component MonoBehaviour. Fixing.

看下图,正常情况下prefab文件中区域1和区域2是对应的,如果不对应会报以上错误。

Guess you like

Origin www.cnblogs.com/luguoshuai/p/12323186.html