阅读量:0
介绍
Unity批量删除物体上引用丢失的脚本
使用场景
当在外部导入资源时会造成物体上挂载的脚本引用丢失,一个个删除比较麻烦,可以借用这个工具快速实现
工具原理
继承EditorWindow绘制一个自定义的编辑器窗口
加载Assets目录下所有预制体
- 获取其所有子物体的Component组件
- 如果组件为Null则表示丢失
- 将丢失的物体加入待清理列表
遍历待清理列表,通过**GameObjectUtility.RemoveMonoBehavioursWithMissingScript(obj);**进行清理;
使用API
- 高亮显示资源并选中
EditorGUIUtility.PingObject(selectTarget); Selection.activeObject = selectTarget;
- 获取指定文件夹下指定类型得资源路径
Directory.GetFiles("Assets","*.prefab",SearchOption.AllDirectories);
- 显示进度条
if(EditorUtility.DisplayCancelableProgressBar("Title","信息",Rage(0,1))) { EditorUtility.ClearProgressBar(); break; }
- 移除丢失脚本的组件
GameObjectUtility.RemoveMonoBehavioursWithMissingScript(gamoObjList[i]);
- 编辑器下加载资源、保存资源
AssetDatabase.LoadAssetAtPath<GameObject>(paths[i]); AssetDatabase.SaveAssets(); AssetDatabase.Refresh();
代码
using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; namespace Tools.MissingScriptsToolWindowTool { public class MissingScriptsWindowTool : EditorWindow { [MenuItem("Tools/Missing Scripts Window")] public static void ShowWindow() { GetWindow(typeof(MissingScriptsWindowTool),false,"Missing Scripts GameObjects"); } List<GameObject> missGamoObjList = new List<GameObject>(); private void OnEnable() { SelectMissingGameObjects(ref missGamoObjList); } private Vector2 scrollPosition = Vector2.zero; private void OnGUI() { GUILayout.BeginHorizontal(); GUILayout.Box("丢失脚本物体列表:"); if(GUILayout.Button("刷新列表",GUILayout.Width(150))) { SelectMissingGameObjects(ref missGamoObjList); } if(GUILayout.Button("清除无效脚本",GUILayout.Width(150))) { RemoveMissingGameObjects(ref missGamoObjList); } GUILayout.EndHorizontal(); GUILayout.Space(10); if(missGamoObjList.Count == 0) { GUILayout.Label("没有丢失脚本的物体"); return; } scrollPosition = GUILayout.BeginScrollView(scrollPosition); for(int i = 0; i < missGamoObjList.Count; i++) { GUILayout.BeginHorizontal("Box",GUILayout.Height(30)); GUILayout.Label(i.ToString(),"AssetLabel",GUILayout.Width(40)); GUILayout.Space(10); if(GUILayout.Button(missGamoObjList[i].name,"AnimLeftPaneSeparator")) { GameObject selectTarget = missGamoObjList[i]; while(selectTarget.transform.parent != null) { selectTarget = selectTarget.transform.parent.gameObject; } EditorGUIUtility.PingObject(selectTarget); Selection.activeObject = selectTarget; } GUILayout.EndHorizontal(); GUILayout.Space(5); } GUILayout.EndScrollView(); } private static void SelectMissingGameObjects(ref List<GameObject> gameObjList) { gameObjList.Clear(); string[] paths = Directory.GetFiles("Assets","*.prefab",SearchOption.AllDirectories); for(int i = 0; i < paths.Length; i++) { if(EditorUtility.DisplayCancelableProgressBar("查找GameObject···","数量 : " + i,(float)i / paths.Length)) { EditorUtility.ClearProgressBar(); break; } GameObject tempObj = AssetDatabase.LoadAssetAtPath<GameObject>(paths[i]); if(tempObj != null) { Transform[] transArr = tempObj.GetComponentsInChildren<Transform>(); for(int j = 0; j < transArr.Length; j++) { Component[] components = transArr[j].GetComponents<Component>(); for(int k = 0; k < components.Length; k++) { if(components[k] == null) { if(!gameObjList.Contains(transArr[j].gameObject)) gameObjList.Add(transArr[j].gameObject); } } } } } EditorUtility.ClearProgressBar(); } private static void RemoveMissingGameObjects(ref List<GameObject> gameObjList) { if(gameObjList.Count == 0) return; for(int i = 0; i < gameObjList.Count; i++) { GameObjectUtility.RemoveMonoBehavioursWithMissingScript(gameObjList[i]); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); gameObjList.Clear(); } } }