/// <summary>
/// 移除GameObject下所有节点的指定组件
/// </summary>
/// <typeparam name="T">要移除的组件</typeparam>
/// <param name="root">清理的根节点</param>
public static void TrimComponent<T>(GameObject root) where T:Component
{
if(null == root) return;
T[] cmps = root.GetComponentsInChildren<T>(true);
List<SerializedObject> modifiedGos = new List<SerializedObject>(cmps.Length);
foreach (var cmp in cmps)
{
SerializedObject obj = new SerializedObject(cmp.gameObject);
SerializedProperty prop = obj.FindProperty("m_Component");
// 这里再次找组件,只是为了找到目标组件在GameObject上挂载的位置
Component[] allCmps = cmp.gameObject.GetComponents<Component>();
for (int i = 0; i < allCmps.Length; ++i)
{
if (allCmps[i] == cmp)
{
prop.DeleteArrayElementAtIndex(i);
break;
}
}
modifiedGos.Add(obj);
}
foreach (SerializedObject so in modifiedGos)
{
// Apply之后cmps里的所有组件都会被销毁,导致后面的清理无法执行,
// 所以将SO对象缓存,最后一起清理。
so.ApplyModifiedProperties();
}
}
使用Demo,清理LanguageImage组件。
/// <summary>
/// 清理不用的组件
/// </summary>
[MenuItem("Assets/Tools/清理组件")]
public static void TrimComponent()
{
TrimComponent<LanguageImage>(Selection.activeGameObject);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}