跑游戏发现有几十条这个日志:
第一个网址序列化物体,获取属性删除,只能删除父节点的空脚本。百度了很多网页,没有办法获取预设上面的所有property,最后实在是没办法,干脆用读取文件的方式删除空脚本。
如下图,删除文件后,就是删除红色部分文本,思路是:通过guid判断脚本存在与否,不存在,则匹配到fileID然后删除这些文本。
重要具体代码如下:主要是从后往前删除。
具体片段代码如下:
public enum FindItemType { FindUI = 0, FindObj = 1, }
[MenuItem("Assets/ClearMissingScripts")] /// <summary> /// 删除预设上面丢失的脚本 /// </summary> static void ClearMissingScripts() { //测试一个 //List<GameObject> prefabList = new List<GameObject>(Selection.gameObjects);//GetAllUIPrefab(); List<GameObject> prefabList = GetAllGameObjects(FindItemType.FindObj); int prefabCount = prefabList.Count; Debug.Log("prefabCount = " + prefabCount); for (int i = prefabCount - 1; i >= 0; i--) { DeleteMissingScripts(prefabList[i]); } AssetDatabase.SaveAssets(); Debug.Log("ClearMissingScripts Success"); } static void DeleteMissingScripts(GameObject obj) { Regex guidRegex = new Regex("m_Script: {fileID: (.*), guid: (?<GuidValue>.*?), type:"); Regex fileRegex = new Regex("--- !u!(?<groupNum>.*?) &(?<fileID>.*?)\r\n"); int fileStrLenght = 30; string filePath = AssetDatabase.GetAssetPath(obj); string s = File.ReadAllText(filePath); string groupSpilChar = "---"; string fileStr = ""; bool isChange = false; MatchCollection matchList = guidRegex.Matches(s); if (matchList != null) { for (int i = matchList.Count - 1; i >= 0; i--) { string guid = matchList[i].Groups["GuidValue"].Value; if(AssetDatabase.GUIDToAssetPath(guid) == ""){ isChange = true; int startIndex = s.LastIndexOf(groupSpilChar, matchList[i].Index); int endIndex = s.IndexOf(groupSpilChar, matchList[i].Index); Match fileMatch = fileRegex.Match(s.Substring(startIndex, fileStrLenght)); fileStr = "- "+ fileMatch.Groups["groupNum"].Value + ": {fileID: "+fileMatch.Groups["fileID"].Value + "}\r\n "; s = s.Replace(s.Substring(startIndex, endIndex - startIndex), ""); s = s.Replace(fileStr, ""); } } } if (isChange) { File.WriteAllText(filePath, s); Debug.Log(obj.name + " missing scripts destory success!"); } }
/// <summary> /// 获取所有的 /// </summary> /// <returns></returns> static List<GameObject> GetAllGameObjects(FindItemType type) { Object[] allObjs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); List<Object> allObjsList = new List<Object>(allObjs); List<GameObject> prefabList = new List<GameObject>(); int count = allObjsList.Count; for (int i = count - 1; i >= 0; i--) { switch (type) { case FindItemType.FindObj: if (IsFindObject(allObjsList[i])) { prefabList.Add((GameObject)allObjsList[i]); } break; //case FindItemType.FindUI: // if (IsFindUIPrefab(allObjsList[i])) { // prefabList.Add((GameObject)allObjsList[i]); // } // break; } } return prefabList; } static bool IsFindObject(UnityEngine.Object obj) { if (obj.GetType() != typeof(GameObject)) { return false; } return true; }
另外在给出找出MissingScripts的脚本:
public class FindMissingScripts : MonoBehaviour { public bool isRun = false; void Start() { } void Update() { if (isRun) { GameObject[] prefabList = GameObject.FindObjectsOfType<GameObject>(); if (prefabList == null) return; int prefabCount = prefabList.Length; // Debug.Log("prefabCount = " + prefabCount); for (int i = prefabCount - 1; i >= 0; i--) { Component[] components = prefabList[i].GetComponentsInChildren<Component>(); if (components == null) continue; int findIndex = System.Array.FindIndex<Component>(components, (item) => { return item == null; }); if (findIndex != -1) { Debug.LogError("000000000000000000find item: " + prefabList[i].name + "|" + components[findIndex - 1].name); } } } } }直接挂在一个全局不删除的物体上面,便于查看是否清理干净,至于场景上面挂的建议手动删除。