- Home /
Sort by Sibling Index
I need to sort a list of arbitrary transforms by their sibling index. But it has to be global. Essentially I want them in the order they appear in the hierarchy and are rendered under the new UI system. But the transforms themselves can be from anywhere in the hierarchy.
For example, I might have references to the highlighted children and I need to sort them by the order they will be rendered by the new UI system.
EDIT: clarified question
Answer by troien · Nov 03, 2014 at 03:51 PM
I think the following piece of code does what you want it to do (I didn't fully test it yet, but I believe this should always work).
Note, this solution might be slow if you do it often, especially if your list is very long.
The code of the comparer:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Example : IComparer<Transform>
{
public int Compare(Transform x, Transform y)
{
if (x == y)
return 0;
if (y.IsChildOf(x))
{
return -1;
}
if (x.IsChildOf(y))
{
return 1;
}
List<Transform> xparentList = GetParents(x);
List<Transform> yparentList = GetParents(y);
for (int xIndex = 0; xIndex < xparentList.Count; xIndex++)
{
if (y.IsChildOf(xparentList[xIndex]))
{
int yIndex = yparentList.IndexOf(xparentList[xIndex]) - 1;
xIndex -= 1;
return xparentList[xIndex].GetSiblingIndex() - yparentList[yIndex].GetSiblingIndex();
}
}
return xparentList[xparentList.Count - 1].GetSiblingIndex() - yparentList[yparentList.Count - 1].GetSiblingIndex();
}
private List<Transform> GetParents(Transform t)
{
List<Transform> parents = new List<Transform>();
parents.Add(t);
while (t.parent != null)
{
parents.Add(t.parent);
t = t.parent;
}
return parents;
}
}
How you can use it:
public class Example2 : MonoBehaviour
{
public Transform[] list;
public void Start()
{
List<Transform> newList = new List<Transform>(list);
newList.Sort(new Example());
for (int i = 0; i < newList.Count; i++)
{
Debug.Log(newList[i].name);
}
}
}
Obviously you should rename the Example class if you use this ;)
This is actually twice as fast the answer posted by hu90, and it seems to work much better! Thanks very much! You've restored my faith in Unity Answers :)
Answer by hu90 · Nov 03, 2014 at 02:40 PM
This function returns a list of all the children of the transform provided, in the order they would appear in the Hierarchy panel :
List<Transform> ChildTransformsSorted(Transform t) {
List<Transform> sorted = new List<Transform>();
for (int i = 0; i < t.childCount; i++) {
Transform child = t.GetChild(i);
sorted.Add( child );
sorted.AddRange( ChildTransformsSorted(child) );
}
return sorted;
}
A few highlights :
The function works in a recursive way
The list does not include the transform passed as a parameter
The objects I have are placed arbitrarily in the hierarchy. I've edited the question to clarify.
Thanks for the clarification.
The function GetGlobalIndex
will return a float for any transform you pass to it. The further the transform is in the hierarchy list, the bigger that float is.
GetDepthInHierarchy
is used by GetGlobalIndex
, no need to call it directly.
float GetGlobalIndex(Transform t) {
if (t.parent == null)
return t.GetSiblingIndex();
else
return ((float)(t.GetSiblingIndex()+1)/(t.parent.childCount+1)) / $$anonymous$$athf.Pow(10, GetDepthInHierarchy(t)-1) + GetGlobalIndex(t.parent);
}
int GetDepthInHierarchy(Transform t) {
if (t.parent == null)
return 0;
else
return 1 + GetDepthInHierarchy(t.parent);
}
So to sort a collection of transforms, you could write :
Transform[] mySortedTransformList = myTransformList.OrderBy(t => GetGlobalIndex(t)).ToArray();
I'll add this to the actual answer if it helps.
That's exactly that I was looking for, but I wasn't sure how I could it mathematically! I'll test it out now!
I tested it and I thought it worked beautifully, but after a child depth of 8, it starts to sort incorrectly :(
Your answer
![](https://koobas.hobune.stream/wayback/20220613170630im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
m_TransformInfo.localAABB.IsValid() 0 Answers
Converting UI RectTransform to Screen Pixel and vice-versa 5 Answers
Better way to make big 2D Game. UI Canvas, Transform calculation, animation 0 Answers
Get position of specific letter in UI Text 4 Answers
Highest sibling but though not visually not on top 2 Answers