#if UNITY_EDITOR using UnityEngine; using UnityEditor; using System.Text.RegularExpressions; using System.Linq; namespace Test_2022.Utils { public class HierarchyCleaner : EditorWindow { private static bool removeRecursively = false; [MenuItem("Tools/Hierarchy/Remove Name Suffixes (e.g. \" (1)\")")] private static void CleanSelectedChildren() { GameObject[] selectedObjects = Selection.gameObjects; if (selectedObjects.Length == 0) { EditorUtility.DisplayDialog("提示", "请先选择一个父对象!", "确定"); return; } Regex regex = new Regex(@"\s\(\d+\)$"); Undo.RecordObjects(selectedObjects, "Clean Names"); int count = 0; foreach (GameObject parent in selectedObjects) { count += CleanChildrenNames(parent.transform, regex); } Debug.Log($"已清理 {count} 个对象的名称后缀。"); } [MenuItem("Tools/Hierarchy/Open Cleaner Window...")] private static void ShowWindow() { var window = GetWindow("Hierarchy清理工具"); window.Show(); } private void OnGUI() { GUILayout.Label("Hierarchy 名称清理工具", EditorStyles.boldLabel); GUILayout.Space(10); removeRecursively = EditorGUILayout.ToggleLeft(" 递归清理所有子层级 (Recursive)", removeRecursively); GUILayout.Space(15); if (GUILayout.Button("去除选中对象子物体的序号后缀", GUILayout.Height(40))) { CleanSelectedWithOptions(); } GUILayout.Space(10); EditorGUILayout.HelpBox( "功能说明:\n" + "移除对象名称末尾的 \" (1)\", \" (2)\" 等自动生成的后缀。\n" + "例如: \"Box (1)\" -> \"Box\"\n" + "注意: \"Box_1\" 或 \"Level1\" 不会受影响。", MessageType.Info ); } private static void CleanSelectedWithOptions() { GameObject[] selectedObjects = Selection.gameObjects; if (selectedObjects.Length == 0) { EditorUtility.DisplayDialog("提示", "请先选择一个父对象!", "确定"); return; } Regex regex = new Regex(@"\s\(\d+\)$"); Undo.RecordObjects(selectedObjects, "Clean Names"); int count = 0; foreach (GameObject parent in selectedObjects) { if (removeRecursively) { count += CleanChildrenNamesRecursive(parent.transform, regex); } else { count += CleanChildrenNames(parent.transform, regex); } } EditorUtility.DisplayDialog("完成", $"清理完成!共修改了 {count} 个对象的名称。", "确定"); } private static int CleanChildrenNames(Transform parent, Regex regex) { int modifiedCount = 0; for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (regex.IsMatch(child.name)) { Undo.RecordObject(child.gameObject, "Rename Object"); string oldName = child.name; child.name = regex.Replace(oldName, ""); modifiedCount++; } } return modifiedCount; } private static int CleanChildrenNamesRecursive(Transform parent, Regex regex) { int modifiedCount = CleanChildrenNames(parent, regex); for (int i = 0; i < parent.childCount; i++) { Transform child = parent.GetChild(i); if (child.childCount > 0) { modifiedCount += CleanChildrenNamesRecursive(child, regex); } } return modifiedCount; } [MenuItem("GameObject/Remove Name Suffixes (Clean)", false, 11)] private static void ContextMenuClean() { CleanSelectedChildren(); } } } #endif