• 对于资源上MissingScript的清理方案讨论


      Unity工程随着复杂度的提升,常会有Prefab上的脚本丢失的情况,如下图所示:

      

      首先失去关联的脚本,是没有线索找到原来是什么文件的,那么有没有办法批处理将这些MissingScript进行一下清理呢?就我使用的Unity4.6所提供的接口来说,没有非常完美的解决办法,但有一些还算可以用来解决问题的做法。

      方法1:找到所有包含有Missing脚本的Prefab,然后逐个手动删除。

      方法2:通过代码自动批处理解决。

      第一种方法比较笨拙,对于资源量不是很大的工程,可以这样做,查找Missing脚本Prefab的代码如下:

    using UnityEngine;
    using UnityEditor;
    using System.Collections;
    using System.Collections.Generic;
    
    public class ClearMissingScript 
    {
        [MenuItem("Custom/SelectMissing")]
        static void SelectMissing(MenuCommand command)
        {
            string []guids=AssetDatabase.FindAssets("t:Prefab", ["Assets/PrefabDir"]);
    
            List<GameObject> selection = new List<GameObject>();
    
            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                GameObject obj=AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;
                Component[] cs = obj.GetComponents<Component>();
    
                foreach (Component c in cs)
                {
                    if (c == null)
                    {
                        selection.Add(obj);
                    }
                }
            }
    
            Selection.objects = selection.ToArray();
        }
    }

      上面的脚本会帮你自动选中所有的包含脚本丢失的Prefab,有耐心的话就挨个处理吧...

       第二种方法会智能一下,但是有一些问题,不确定是不是我代码写的有问题哈,代码如下所示:

      

    public class CleanUpMissingScripts
    {
        [MenuItem("Edit/CleanupMissingScripts &c")]
        public static void CleanupMissingScripts()
        {
            for(int i = 0; i < Selection.gameObjects.Length; ++i)
            {
                var gameObject = Selection.gameObjects[i];
    
                var components = gameObject.GetComponents<Component>();
    
                SerializedObject serializedObject = new SerializedObject(gameObject);
    
                SerializedProperty prop = serializedObject.FindProperty("m_Component");
    
                int r = 0;
    
                for(int j = 0; j < components.Length; j++)
                {
                    if(components[j] == null)
                    {
                        prop.DeleteArrayElementAtIndex(j - r);
                        r++;
                    }
                }
    
                serializedObject.ApplyModifiedProperties();
            }
    
            AssetDatabase.Refresh();
        }
    }

      这个脚本利用SerializedObject和SerializedProperty两个类来进行处理,思路上比较清晰,但是有问题:处理完之后看似清除了所有的Missing脚本,但一运行游戏,这些Missing脚本又回来了,于是换个思路,我们先将处理asset实例化出来,然后对实例化后的GameObject进行处理,再将处理完毕的GameObject写进asset,代码如下所示:

    public class MissingScriptsEditor : EditorWindow
    {
        private static EditorWindow window;
        private List<GameObject> lstTmp = new List<GameObject>();
    
        [MenuItem("Custom/MissingScripteEditor")]
        private static void Execute()
        {
            if (window == null)
                window = (MissingScriptsEditor)GetWindow(typeof(MissingScriptsEditor));
            window.Show();
        }
    
        private void OnGUI()
        {
            GUILayout.BeginVertical("box");
            if (GUILayout.Button("CleanUpSelection", GUILayout.Height(30f)))
            {
                CleanUpSelection();
            }
            GUILayout.EndVertical();
        }
    
        private void CleanUpSelection()
        {
            var lstSelection = Selection.GetFiltered(typeof(GameObject), SelectionMode.DeepAssets);
    
            for(int i = 0; i < lstSelection.Length; ++i)
            {
                EditorUtility.DisplayProgressBar("Checking", "逐个分析中,请勿退出!", (float)i / (float)lstSelection.Length);
                var gameObject = lstSelection[i] as GameObject;
                var components = gameObject.GetComponents<Component>();
    
                for (int j = 0; j < components.Length; j++)
                {
                    // 如果组建为null
                    if (components[j] == null)
                    {
                        CleanUpAsset(gameObject);
                        break;
                    }
                }
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
    
            foreach (var go in lstTmp)
            {
                GameObject.DestroyImmediate(go);
            }
            lstTmp.Clear();
        }
    
        private void CleanUpAsset(Object asset)
        {
            GameObject go = PrefabUtility.InstantiatePrefab(asset) as GameObject;
    
            // 创建一个序列化对象
            SerializedObject serializedObject = new SerializedObject(go);
            // 获取组件列表属性
            SerializedProperty prop = serializedObject.FindProperty("m_Component");
    
            var components = go.GetComponents<Component>();
            int r = 0;
            for (int j = 0; j < components.Length; j++)
            {
                // 如果组建为null
                if (components[j] == null)
                {
                    // 按索引删除
                    prop.DeleteArrayElementAtIndex(j - r);
                    r++;
                }
            }
    
            // 应用修改到对象
            serializedObject.ApplyModifiedProperties();
    
            // 将数据替换到asset
            // PrefabUtility.ReplacePrefab(go, asset);
            PrefabUtility.CreatePrefab(AssetDatabase.GetAssetPath(asset), go);
    
            go.hideFlags = HideFlags.HideAndDontSave;
    
            // 删除临时实例化对象
            lstTmp.Add(go);
        }
    
    }

      

      此代码提供了简单的编辑器界面,对于在Project中选中的Prefab进行处理,处理完之后可以很干净的删除所有的MissingScript引用,但是在Ctrl+S或运行游戏的时候会出现一些额外的提示,或者会直接崩掉。但是,重新开启Unity之后就好了,并且问题也解决了。

      所以建议使用这种方法,并且在处理完之后重启一下Unity,然后问题成功解决!

      上面的代码仅供参考,并且此处贴出编辑器处理完之后的报错,希望知道此问题的人能够留言帮我解答一下原因:

      

     

     

     

  • 相关阅读:
    [BZOJ1565][NOI2009]植物大战僵尸
    [BZOJ1566][NOI2009]管道取珠
    [BZOJ4104][Thu Summer Camp 2015]解密运算
    [BZOJ1003][ZJOI2006]物流运输
    [BZOJ3790]神奇项链
    指纹模块原理_光学指纹模块原理
    Ubuntu 16.04无损分区大小调整工具Gparted
    16进制转换10进制
    Memory Ordering in Modern Microprocessors
    python 多态
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/4702688.html
Copyright © 2020-2023  润新知