Search Unity

TextMesh Pro Text stuttering because it's in a vertical layout?

Discussion in 'UGUI & TextMesh Pro' started by James-Sullivan, Jan 21, 2020.

  1. James-Sullivan

    James-Sullivan

    Joined:
    Jun 15, 2015
    Posts:
    128
    I'm trying to get text to fade in one letter at a time and it works, except when I make the text a child of a Vertical Layout Group. Then the text often stutters whenever a letter gets added as you can see in the video below. The top text is the child of a Vertical Layout Group and the bottom is the exact same object and scripts, just without being the child of a layout group.



    I tried forcing a rebuild of the layout whenever a letter got added but that didn't see to have any affect.

    I really have no idea why the layout would be messing with the text mesh in a way that would cause this. Do you have any ideas? Thanks in advance.

    Here's the scripts for the letter fading.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using TMPro;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6.  
    7. public class FadeLetterDebug : MonoBehaviour
    8. {
    9.     // Start is called before the first frame update
    10.     void Start()
    11.     {
    12.         StartCoroutine(AddLetters());
    13.     }
    14.  
    15.     private IEnumerator AddLetters()
    16.     {
    17.         FadeLetterController fadeLetterController = GetComponent<FadeLetterController>();
    18.         TextMeshProUGUI textComp = GetComponent<TextMeshProUGUI>();
    19.  
    20.         while (true)
    21.         {
    22.             textComp.text += "A";
    23.             fadeLetterController.CharAdded();
    24.             LayoutRebuilder.ForceRebuildLayoutImmediate(transform.parent.GetComponent<RectTransform>());
    25.            
    26.             yield return new WaitForSeconds(1f);
    27.         }
    28.        
    29.     }
    30.  
    31. }
    32.  
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using TMPro;
    6. using System.Text;
    7.  
    8. [RequireComponent(typeof(TextMeshProUGUI))]
    9. public class FadeLetterController : MonoBehaviour
    10. {
    11.     private TextMeshProUGUI textComponent;
    12.  
    13.     [SerializeField] private float textSpeed = 1.5f;
    14.  
    15.     private List<LetterAlpha> letterAlphas = new List<LetterAlpha>();
    16.  
    17.     private int currentLetter = 0;
    18.  
    19.     class LetterAlpha
    20.     {
    21.         public int CharIndex { get; set; }
    22.         public int Alpha { get; set; } = 0;
    23.  
    24.         // Stores a reference to the text object this letter belongs to
    25.         public TextMeshProUGUI TextComp { get; set; }
    26.  
    27.         public LetterAlpha(int index, TextMeshProUGUI text)
    28.         {
    29.             CharIndex = index;
    30.             TextComp = text;
    31.         }
    32.     }
    33.  
    34.     private void Awake()
    35.     {
    36.         textComponent = GetComponent<TextMeshProUGUI>();
    37.     }
    38.    
    39.     public void CharAdded()
    40.     {
    41.         // Force the text object to update right away so we can have geometry to modify right from the start.
    42.         textComponent.ForceMeshUpdate();
    43.  
    44.         StartCoroutine(FadeInLetter(currentLetter));
    45.  
    46.         currentLetter++;
    47.     }
    48.  
    49.     // Increases the given letter's alpha value over time in letterAlphas until its reaches maximum
    50.     private IEnumerator FadeInLetter(int letterIndex)
    51.     {
    52.         LetterAlpha letterAlpha = new LetterAlpha(letterIndex, textComponent);
    53.  
    54.         letterAlphas.Add(letterAlpha);
    55.  
    56.         while (letterAlpha.Alpha < 255)
    57.         {
    58.             letterAlpha.Alpha += (int)((Time.deltaTime / (textSpeed + 2f)) * 255);
    59.  
    60.             if (letterAlpha.Alpha > 255)
    61.             {
    62.                 letterAlpha.Alpha = 255;
    63.             }
    64.  
    65.             yield return null;
    66.         }
    67.  
    68.         letterAlphas.Remove(letterAlpha);
    69.     }
    70.  
    71.     // Sets each letter with an entry in letterAlphas to its correct alpha value
    72.     private void UpdateLetterAlphas()
    73.     {
    74.         //Debug.Log("--------------");
    75.         foreach (LetterAlpha letterAlpha in letterAlphas)
    76.         {
    77.             int letterIndex = letterAlpha.CharIndex;
    78.             int alpha = letterAlpha.Alpha;
    79.  
    80.             //Debug.Log("letterIndex = " + letterIndex + " alpha = " + alpha);
    81.  
    82.             TMP_TextInfo textInfo = letterAlpha.TextComp.textInfo;
    83.            
    84.             Color32 c0 = letterAlpha.TextComp.color;
    85.  
    86.             // Get the index of the material used by the current character.
    87.             int materialIndex = textInfo.characterInfo[letterIndex].materialReferenceIndex;
    88.  
    89.             // Get the vertex colors of the mesh used by this text element (character or sprite).
    90.             Color32[] newVertexColors = textInfo.meshInfo[materialIndex].colors32;
    91.  
    92.             // Get the index of the first vertex used by this text element.
    93.             int vertexIndex = textInfo.characterInfo[letterIndex].vertexIndex;
    94.  
    95.             c0 = new Color32(c0.r, c0.g, c0.b, (byte)alpha);
    96.  
    97.             newVertexColors[vertexIndex + 0] = c0;
    98.             newVertexColors[vertexIndex + 1] = c0;
    99.             newVertexColors[vertexIndex + 2] = c0;
    100.             newVertexColors[vertexIndex + 3] = c0;
    101.  
    102.             // Pushes (all) updated vertex data to the appropriate meshes when using either the Mesh Renderer or CanvasRenderer.
    103.             letterAlpha.TextComp.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    104.         }
    105.         //Debug.Log("--------------");
    106.     }
    107.  
    108.     // Updates late so that all of the FadeInLetter coroutines will have run by now
    109.     private void LateUpdate()
    110.     {
    111.         UpdateLetterAlphas();
    112.     }
    113. }
    114.