Search Unity

Problem with TextMeshProUGUI components in hierarchy

Discussion in 'UGUI & TextMesh Pro' started by PNordlund, Jun 3, 2018.

  1. PNordlund

    PNordlund

    Joined:
    Nov 20, 2013
    Posts:
    48
    This code in TMPro_UGUI_Private.cs seems to fail when there are multiple text components recursively in the hierarchy, i.e. I have one GameObject with TextMeshProUGUI component on it, and then other GameObjects as it's children - if they all have the TMP_SubMeshUI component somewhere, the code fails when there are more than 7 of them.

    protected TMP_SubMeshUI[] m_subTextObjects = new TMP_SubMeshUI[8];

    // Check to make sure Sub Text Objects are tracked correctly in the event a Prefab is used.
    TMP_SubMeshUI[] subTextObjects = GetComponentsInChildren<TMP_SubMeshUI>();
    if (subTextObjects.Length > 0)
    {
    for (int i = 0; i < subTextObjects.Length; i++)
    m_subTextObjects[i + 1] = subTextObjects;
    }
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Can you post an image of this hierarchy so I can see the top parent, each of the text objects and sub text objects?
     
  3. TheZombieKiller

    TheZombieKiller

    Joined:
    Feb 8, 2013
    Posts:
    265
    Encountered this issue today on a project, it was preventing builds. The hierarchy in question looks like the following:



    Upon examination of the problematic areas of the TextMeshPro code, you will notice a few things.

    Code (CSharp):
    1.  
    2. // Check to make sure Sub Text Objects are tracked correctly in the event a Prefab is used.
    3. TMP_SubMeshUI[] subTextObjects = GetComponentsInChildren<TMP_SubMeshUI>();
    4. if (subTextObjects.Length > 0)
    5. {
    6.     for (int i = 0; i < subTextObjects.Length; i++)
    7.         m_subTextObjects[i + 1] = subTextObjects[i];
    8. }
    1. The loop changes the value of m_subTextObjects[i +1]. This array has a size of 8, as seen earlier in the file.
    2. subTextObjects is retrieved with GetComponentsInChildren, which is also grabbing the components from ScoreText, causing the loop to cross 7 iterations, causing an array out of bounds exception.

    The solution? Only grab components from children with a depth of 1, and ensure the loop does not exceed 7 iterations. The code I used to solve the bug can be seen below.

    Code (CSharp):
    1.  
    2. // Check to make sure Sub Text Objects are tracked correctly in the event a Prefab is used.
    3. var subTextObjects = new List<TMP_SubMeshUI>();
    4. for (var i = 0; i < transform.childCount; i++)
    5. {
    6.     var component = transform.GetChild(i).GetComponent<TMP_SubMeshUI>();
    7.     if (component) subTextObjects.Add(component);
    8. }
    9.  
    10. if (subTextObjects.Count > 0)
    11. {
    12.     // todo: maybe make m_subTextObjects a dynamic array?
    13.     for (int i = 0; i < Math.Min(7, subTextObjects.Count); i++)
    14.         m_subTextObjects[i + 1] = subTextObjects[i];
    15. }
    16.