Unity bug3_删除预设上的丢失脚本Missing

跑游戏发现有几十条这个日志:

第一个网址序列化物体,获取属性删除,只能删除父节点的空脚本。百度了很多网页,没有办法获取预设上面的所有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);
                }
            }
        }
    }
}
直接挂在一个全局不删除的物体上面,便于查看是否清理干净,至于场景上面挂的建议手动删除。


猜你喜欢

转载自blog.csdn.net/xj1009420846/article/details/80586274