Files
Echo/Assets/_Project/Scripts/Utils/HierarchySorter.cs
T

181 lines
5.8 KiB
C#
Raw Normal View History

2026-07-08 19:53:15 +08:00
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Linq;
namespace Test_2022.Utils
{
public class HierarchySorter : EditorWindow
{
private static bool includeInactive = true;
private static bool sortRecursively = false;
[MenuItem("Tools/Hierarchy/Sort Immediate Children Only (A-Z)")]
private static void SortSelectedChildren()
{
GameObject[] selectedObjects = Selection.gameObjects;
if (selectedObjects.Length == 0)
{
EditorUtility.DisplayDialog("提示", "请先选择一个父对象!", "确定");
return;
}
foreach (GameObject parent in selectedObjects)
{
SortChildren(parent.transform);
}
}
[MenuItem("Tools/Hierarchy/Sort All Descendants (Recursive)")]
private static void SortSelectedChildrenRecursive()
{
GameObject[] selectedObjects = Selection.gameObjects;
if (selectedObjects.Length == 0)
{
EditorUtility.DisplayDialog("提示", "请先选择一个父对象!", "确定");
return;
}
foreach (GameObject parent in selectedObjects)
{
SortChildrenRecursive(parent.transform);
}
}
[MenuItem("Tools/Hierarchy/Open Sort Window...")]
private static void ShowWindow()
{
var window = GetWindow<HierarchySorter>("Hierarchy排序工具");
window.Show();
}
private void OnGUI()
{
GUILayout.Label("Hierarchy 排序工具", EditorStyles.boldLabel);
GUILayout.Space(10);
includeInactive = EditorGUILayout.ToggleLeft(" 包含非激活对象 (Include Inactive)", includeInactive);
sortRecursively = EditorGUILayout.ToggleLeft(" 递归排序所有子层级 (Recursive)", sortRecursively);
GUILayout.Space(15);
string buttonText = sortRecursively ? "排序选中对象及其所有后代" : "仅排序选中对象的直接子级";
if (GUILayout.Button(buttonText, GUILayout.Height(40)))
{
SortSelectedWithOptions();
}
GUILayout.Space(10);
EditorGUILayout.HelpBox(
sortRecursively
? "模式:递归\n将排序选中对象下的所有层级物体。\n结构会被彻底重新整理。"
: "模式:仅直接子级\n只会排序第一层子对象。\n子对象的子对象保持原样(符合您的需求)。",
MessageType.Info
);
}
private static void SortSelectedWithOptions()
{
GameObject[] selectedObjects = Selection.gameObjects;
if (selectedObjects.Length == 0)
{
EditorUtility.DisplayDialog("提示", "请先选择一个父对象!", "确定");
return;
}
Undo.RecordObjects(selectedObjects, "Sort Children");
int totalSorted = 0;
foreach (GameObject parent in selectedObjects)
{
if (sortRecursively)
{
totalSorted += SortChildrenRecursive(parent.transform);
}
else
{
totalSorted += SortChildren(parent.transform);
}
}
}
private static int SortChildren(Transform parent)
{
if (parent == null) return 0;
var children = new System.Collections.Generic.List<Transform>();
for (int i = 0; i < parent.childCount; i++)
{
children.Add(parent.GetChild(i));
}
if (!includeInactive)
{
children = children.Where(c => c.gameObject.activeSelf).ToList();
}
if (children.Count <= 1) return 0;
var sortedChildren = children.OrderBy(c => c.name).ToList();
bool orderChanged = false;
for (int i = 0; i < children.Count; i++)
{
if (children[i] != sortedChildren[i])
{
orderChanged = true;
break;
}
}
if (orderChanged)
{
for (int i = 0; i < sortedChildren.Count; i++)
{
Undo.SetTransformParent(sortedChildren[i], parent, "Sort Children");
sortedChildren[i].SetSiblingIndex(i);
}
}
return 1;
}
private static int SortChildrenRecursive(Transform parent)
{
if (parent == null) return 0;
int totalSorted = SortChildren(parent);
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
if (child.childCount > 0)
{
totalSorted += SortChildrenRecursive(child);
}
}
return totalSorted;
}
[MenuItem("GameObject/Sort Children Alphabetically", false, 0)]
private static void ContextMenuSort()
{
SortSelectedChildren();
}
[MenuItem("GameObject/Sort Children Alphabetically (Recursive)", false, 1)]
private static void ContextMenuSortRecursive()
{
SortSelectedChildrenRecursive();
}
}
}
#endif