0
\$\begingroup\$

I have a list of GameObject , and I need to know which one is the last in the hierarchy ( This is for a UI system, So is kind of 'which one is showing up')

I have a cursor managed by GamePad , and I use Raycast to see if he clicked something, It give me an array of Gameobjects but I need to know which one is showing up(on top of the others) to click on it

Example this is my full hierarchy:

GameObject A
        GameObject B
        GameObject C
GameObject D
        GameObject E
        GameObject F
GameObject G
          GameObject H
               GameObject I
           GameObject J 

The list of raycast contain 'GameObject D','GameObject A','GameObject I'

How I cand find that 'GameObject I' is the last one? they don't have a common root

\$\endgroup\$
2

1 Answer 1

2
\$\begingroup\$

Here is a script I've made to determine which Transform is the "front most" according to the hierarchy. But be careful, if one of the "candidates" has a higher z value, the function will return the wrong result :

// Call this function by giving an array of transforms
public Transform GetFrontMost( Transform[] transforms )
{
    List<List<int>> siblingIndices = new List<List<int>>();

    for ( int i = 0 ; i < transforms.Length ; i++ )
    {
        siblingIndices.Add( GetSiblingIndices( transforms[i] ) );
    }

    Transform frontMost = null;
    int depth = 0;
    bool conflict = true;
    int maxSibling = -1;

    while ( conflict )
    {
        conflict = false;
        maxSibling = -1;

        for ( int transformIndex = 0 ; transformIndex < siblingIndices.Count ; transformIndex++ )
        {
            if ( depth < siblingIndices[transformIndex].Count )
            {
                if ( siblingIndices[transformIndex][depth] > maxSibling )
                {
                    conflict = false;
                    maxSibling = siblingIndices[transformIndex][depth];
                    frontMost = transforms[transformIndex];
                }
                else if ( siblingIndices[transformIndex][depth] == maxSibling )
                {
                    conflict = true;
                    frontMost = null;
                }
            }
        }

        depth++;
    }

    return frontMost;
}

private List<int> GetSiblingIndices( Transform t )
{
    if ( t.parent == null )
        return new List<int>() { t.GetSiblingIndex() };
    else
    {
        List<int> list = GetSiblingIndices( t.parent );
        list.Add( t.GetSiblingIndex() );
        return list;
    }
}

Supposing you have a hierarchy as below, if you give 'GameObject D','GameObject A','GameObject I', the function should return 'GameObject I'.

GameObject A
        GameObject B
        GameObject C
GameObject D
        GameObject E
        GameObject F
GameObject G
          GameObject H
               GameObject I
           GameObject J 

In the code above :

  1. For each "candidates", you get an array containing the sibling indices of all its parent
  2. You compare the indices, candidate by candidate. If you find one candidate with a higher sibling index for a given depth, you have found the frontmost element
  3. Else, you go deeper in the hierarchy to make the comparisons
\$\endgroup\$
2
  • \$\begingroup\$ Very usefull script thanks! However I found that GraphicRaycaster give the results in inverse order of the hierarchy! So I can simply check if the graphic is a clickable ! \$\endgroup\$
    – D4rWiNS
    Commented Sep 26, 2017 at 7:53
  • \$\begingroup\$ Nice to know! Indeed, it will be simpler in comparison to my script. \$\endgroup\$
    – Hellium
    Commented Sep 26, 2017 at 8:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .