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
\$\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\$
  • \$\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 Sep 26 '17 at 7:53
  • \$\begingroup\$ Nice to know! Indeed, it will be simpler in comparison to my script. \$\endgroup\$ – Hellium Sep 26 '17 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.