| Parameter | Description |
|---|---|
| node | The hierarchy node. |
HierarchyNode A hierarchy node.
Gets the parent of a hierarchy node.
The following example adds an action to a context menu that you can use to select the nearest common ancestor of the GameObjects you have selected in the Hierarchy window. The action appears in the Hierarchy Samples submenu of the context menu. The example uses GetParent to advance two nodes up the hierarchy in a single loop to find their closest common ancestor.
To use this example:
Assets/Editor/SelectCommonAncestor. Scripts in an Editor folder can use the Hierarchy module API without additional setup. If you save the script outside of an Editor folder, you must enable the Hierarchy built-in module in the Package Manager window, which also adds the module to your Player builds.using Unity.Hierarchy; using Unity.Hierarchy.Editor; using UnityEditor; using UnityEngine.UIElements;
namespace Unity.HierarchySamples.Editor { class SelectCommonAncestor { [InitializeOnLoadMethod] static void Initialize() { HierarchyWindow.PopulateContextMenu += OnPopulateContextMenu; }
static void OnPopulateContextMenu(HierarchyWindow window, HierarchyView view, HierarchyViewItem item, DropdownMenu menu) { menu.AppendAction("Hierarchy Samples/Select Common Ancestor", _ => { HierarchyNode commonAncestor = FindCommonAncestor(view);
if (commonAncestor != HierarchyNode.Null && commonAncestor != view.ViewModel.GetRoot()) { view.SetSelection(commonAncestor); view.Frame(commonAncestor); window.UpdateEditorSelection(); } }, _ => view.ViewModel.HasFlagsCount(HierarchyNodeFlags.Selected) < 2 ? DropdownMenuAction.Status.Disabled : DropdownMenuAction.Status.Normal); }
static HierarchyNode FindCommonAncestor(HierarchyView view) { HierarchyViewModel viewModel = view.ViewModel;
// The view is a DFS pre-order flattening, so each subtree occupies a contiguous // index range. Therefore LCA(set) == LCA(min-index node, max-index node) — one // linear scan replaces the previous O(N·D) pairwise fold. int minIndex = int.MaxValue; int maxIndex = int.MinValue; HierarchyNode leftmost = HierarchyNode.Null; HierarchyNode rightmost = HierarchyNode.Null;
foreach (HierarchyNode node in viewModel.EnumerateNodesWithFlags(HierarchyNodeFlags.Selected)) { int index = viewModel.IndexOf(node); if (index < minIndex) { minIndex = index; leftmost = node; } if (index > maxIndex) { maxIndex = index; rightmost = node; } }
if (leftmost == HierarchyNode.Null) return HierarchyNode.Null;
HierarchyNode lca = FindPairwiseLCA(viewModel, leftmost, rightmost);
// A selected node isn't considered its own ancestor, so return its parent instead. if (lca != HierarchyNode.Null && viewModel.HasFlags(lca, HierarchyNodeFlags.Selected)) lca = viewModel.GetParent(lca);
return lca; }
static HierarchyNode FindPairwiseLCA(HierarchyViewModel viewModel, HierarchyNode node1, HierarchyNode node2) { // Move the deeper node up until both nodes are at the same depth, then advance both together in a single loop. while (node1 != node2 && node1 != HierarchyNode.Null && node2 != HierarchyNode.Null) { int depthA = viewModel.GetDepth(node1); int depthB = viewModel.GetDepth(node2); if (depthA >= depthB) { node1 = viewModel.GetParent(node1); } if (depthB >= depthA) { node2 = viewModel.GetParent(node2); } }
return node1; } } }