Search Unity

TextMesh Pro Have words fade in one by one

Discussion in 'UGUI & TextMesh Pro' started by MKrohn, Apr 5, 2018.

  1. MKrohn

    MKrohn

    Joined:
    Apr 5, 2018
    Posts:
    23
    Hi,

    what I am trying to achieve is a text animation where every word fades in individually, one after the other.

    Seemingly, there is a way to access words alpha value individually like this:
    Code (CSharp):
    1. GetComponent<TextMeshPro>.textInfo.wordInfo[0].textComponent.alpha
    So I tried looping through all words and tweening their alpha-values one after the other.
    Sadly, what happens is that always the whole text (all words) is alpha-tweened, most likely because "textComponent" always references the same shared component, or just because all words share the same material.

    Does anybody know of a way to access alpha values of words, individually?
    Or would I need to create a new TextMeshPro-object-instance for each word?
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    See the following post http://digitalnativestudios.com/forum/index.php?topic=1182.msg8986#msg8986

    In that example the fading occurs per character so to achieve a similar result per word, you would iterate over each word. For each word, you would still have to apply the vertex attribute change to each of the characters of the word.

    When working with the TextInfo and the data it contains, remember that it is the resulting output of the text processing. Changing the TextInfo or data contained within has no impact on the text object.
     
    Last edited: Apr 5, 2018
    BitGamey likes this.
  3. MKrohn

    MKrohn

    Joined:
    Apr 5, 2018
    Posts:
    23
    Awesome!! That worked! Many thanks!
     
    Stephan_B likes this.
  4. Pimpace

    Pimpace

    Joined:
    Sep 21, 2017
    Posts:
    41
    Hello Stephan! I know it's an old topic but I'm trying to achieve the opposite of your script. Fade IN char by char with alpha + color. But I couldn't figure out how can I modify your script to do this. I tried
    Code (CSharp):
    1. m_TextComponent.maxVisibleCharacters = currentCharacter;
    and tried to reverse the for cycle, but didn't get to work... :( Or do I need to set all characters's alpha to zero one by one first? Can you point out to me where do I need to modify the script?
     
    James-Sullivan likes this.
  5. su9257

    su9257

    Joined:
    Jun 13, 2017
    Posts:
    27
    Hey, I also encountered the same problem as you. How did you finally solve it?
     
    James-Sullivan likes this.
  6. Pimpace

    Pimpace

    Joined:
    Sep 21, 2017
    Posts:
    41
    I didn't :( Finally I made an ugly workaround with a gradient sprite masked with TMP UGUI object, so it "looks" like it faded out.
     
  7. Marijn_Kiwi

    Marijn_Kiwi

    Joined:
    May 15, 2013
    Posts:
    9
    I slightly modified the script so it would reveal instead of hide. Make sure your
    Code (CSharp):
    1. public Color ColorTint;
    is set to alpha max alpha, otherwise it will never trigger the next char
    Code (CSharp):
    1. if (alpha == 255)
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using TMPro;
    4. using UnityEngine;
    5.  
    6. public class RevealText : MonoBehaviour
    7. {
    8.  
    9.     private TMP_Text m_TextComponent;
    10.  
    11.     public float FadeSpeed = 1.0F;
    12.     public int RolloverCharacterSpread = 10;
    13.     public Color ColorTint;
    14.  
    15.  
    16.     void Awake()
    17.     {
    18.         m_TextComponent = GetComponent<TMP_Text>();
    19.     }
    20.  
    21.  
    22.     void Start()
    23.     {
    24.         StartCoroutine(AnimateVertexColors());
    25.     }
    26.  
    27.  
    28.     /// <summary>
    29.     /// Method to animate vertex colors of a TMP Text object.
    30.     /// </summary>
    31.     /// <returns></returns>
    32.     IEnumerator AnimateVertexColors()
    33.     {
    34.         // Need to force the text object to be generated so we have valid data to work with right from the start.
    35.         m_TextComponent.ForceMeshUpdate();
    36.  
    37.  
    38.         TMP_TextInfo textInfo = m_TextComponent.textInfo;
    39.         Color32[] newVertexColors;
    40.  
    41.         int currentCharacter = 0;
    42.         int startingCharacterRange = currentCharacter;
    43.         bool isRangeMax = false;
    44.  
    45.         while (!isRangeMax)
    46.         {
    47.             int characterCount = textInfo.characterCount;
    48.  
    49.             // Spread should not exceed the number of characters.
    50.             byte fadeSteps = (byte)Mathf.Max(1, 255 / RolloverCharacterSpread);
    51.  
    52.  
    53.             for (int i = startingCharacterRange; i < currentCharacter + 1; i++)
    54.             {
    55.                 // Skip characters that are not visible
    56.                 //if (textInfo.characterInfo[i].isVisible) continue;
    57.  
    58.                 // Get the index of the material used by the current character.
    59.                 int materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
    60.  
    61.                 // Get the vertex colors of the mesh used by this text element (character or sprite).
    62.                 newVertexColors = textInfo.meshInfo[materialIndex].colors32;
    63.  
    64.                 // Get the index of the first vertex used by this text element.
    65.                 int vertexIndex = textInfo.characterInfo[i].vertexIndex;
    66.  
    67.                 // Get the current character's alpha value.
    68.                 byte alpha = (byte)Mathf.Clamp(newVertexColors[vertexIndex + 0].a + fadeSteps, 0, 255);
    69.  
    70.                 // Set new alpha values.
    71.                 newVertexColors[vertexIndex + 0].a = alpha;
    72.                 newVertexColors[vertexIndex + 1].a = alpha;
    73.                 newVertexColors[vertexIndex + 2].a = alpha;
    74.                 newVertexColors[vertexIndex + 3].a = alpha;
    75.  
    76.                 // Tint vertex colors
    77.                 // Note: Vertex colors are Color32 so we need to cast to Color to multiply with tint which is Color.
    78.                 newVertexColors[vertexIndex + 0] = (Color)newVertexColors[vertexIndex + 0] * ColorTint;
    79.                 newVertexColors[vertexIndex + 1] = (Color)newVertexColors[vertexIndex + 1] * ColorTint;
    80.                 newVertexColors[vertexIndex + 2] = (Color)newVertexColors[vertexIndex + 2] * ColorTint;
    81.                 newVertexColors[vertexIndex + 3] = (Color)newVertexColors[vertexIndex + 3] * ColorTint;
    82.  
    83.                 if (alpha == 255)
    84.                 {
    85.                     startingCharacterRange += 1;
    86.  
    87.                     if (startingCharacterRange == characterCount)
    88.                     {
    89.                         // Update mesh vertex data one last time.
    90.                         m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    91.  
    92.                         yield return new WaitForSeconds(1.0f);
    93.  
    94.                         // Reset the text object back to original state.
    95.                         m_TextComponent.ForceMeshUpdate();
    96.  
    97.                         yield return new WaitForSeconds(1.0f);
    98.  
    99.                         // Reset our counters.
    100.                         currentCharacter = 0;
    101.                         startingCharacterRange = 0;
    102.                         //isRangeMax = true; // Would end the coroutine.
    103.                     }
    104.                 }
    105.             }
    106.  
    107.             // Upload the changed vertex colors to the Mesh.
    108.             m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    109.  
    110.             if (currentCharacter + 1 < characterCount) currentCharacter += 1;
    111.  
    112.             yield return new WaitForSeconds(0.25f - FadeSpeed * 0.01f);
    113.         }
    114.     }
    115. }
     
    vozcn, yccore and id0 like this.
  8. Pimpace

    Pimpace

    Joined:
    Sep 21, 2017
    Posts:
    41
    I'm sorry @Marijn_Kiwi, your code is not quite right.

    This is the right way:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4. using TMPro;
    5.  
    6. public class ConsoleSystem : MonoBehaviour
    7. {
    8.     [SerializeField] private TextMeshProUGUI m_TextComponent;
    9.     [SerializeField] private float FadeSpeed = 20.0f;
    10.     [SerializeField] private int RolloverCharacterSpread = 10;
    11.  
    12.  
    13.     void Start()
    14.     {
    15.         StartCoroutine(FadeInText());
    16.     }
    17.  
    18.  
    19.     /// <summary>
    20.     /// Method to animate (fade in) vertex colors of a TMP Text object.
    21.     /// </summary>
    22.     /// <returns></returns>
    23.     IEnumerator FadeInText()
    24.     {
    25.         // Set the whole text transparent
    26.         m_TextComponent.color = new Color
    27.             (
    28.                 m_TextComponent.color.r,
    29.                 m_TextComponent.color.g,
    30.                 m_TextComponent.color.b,
    31.                 0
    32.             );
    33.         // Need to force the text object to be generated so we have valid data to work with right from the start.
    34.         m_TextComponent.ForceMeshUpdate();
    35.  
    36.  
    37.         TMP_TextInfo textInfo = m_TextComponent.textInfo;
    38.         Color32[] newVertexColors;
    39.  
    40.         int currentCharacter = 0;
    41.         int startingCharacterRange = currentCharacter;
    42.         bool isRangeMax = false;
    43.  
    44.         while (!isRangeMax)
    45.         {
    46.             int characterCount = textInfo.characterCount;
    47.  
    48.             // Spread should not exceed the number of characters.
    49.             byte fadeSteps = (byte)Mathf.Max(1, 255 / RolloverCharacterSpread);
    50.  
    51.             for (int i = startingCharacterRange; i < currentCharacter + 1; i++)
    52.             {
    53.                 // Skip characters that are not visible (like white spaces)
    54.                 if (!textInfo.characterInfo[i].isVisible) continue;
    55.  
    56.                 // Get the index of the material used by the current character.
    57.                 int materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
    58.  
    59.                 // Get the vertex colors of the mesh used by this text element (character or sprite).
    60.                 newVertexColors = textInfo.meshInfo[materialIndex].colors32;
    61.  
    62.                 // Get the index of the first vertex used by this text element.
    63.                 int vertexIndex = textInfo.characterInfo[i].vertexIndex;
    64.  
    65.                 // Get the current character's alpha value.
    66.                 byte alpha = (byte)Mathf.Clamp(newVertexColors[vertexIndex + 0].a + fadeSteps, 0, 255);
    67.  
    68.                 // Set new alpha values.
    69.                 newVertexColors[vertexIndex + 0].a = alpha;
    70.                 newVertexColors[vertexIndex + 1].a = alpha;
    71.                 newVertexColors[vertexIndex + 2].a = alpha;
    72.                 newVertexColors[vertexIndex + 3].a = alpha;
    73.  
    74.                 if (alpha == 255)
    75.                 {
    76.                     startingCharacterRange += 1;
    77.  
    78.                     if (startingCharacterRange == characterCount)
    79.                     {
    80.                         // Update mesh vertex data one last time.
    81.                         m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    82.  
    83.                         yield return new WaitForSeconds(1.0f);
    84.  
    85.                         // Reset the text object back to original state.
    86.                         m_TextComponent.ForceMeshUpdate();
    87.  
    88.                         yield return new WaitForSeconds(1.0f);
    89.  
    90.                         // Reset our counters.
    91.                         currentCharacter = 0;
    92.                         startingCharacterRange = 0;
    93.                         //isRangeMax = true; // Would end the coroutine.
    94.                     }
    95.                 }
    96.             }
    97.  
    98.             // Upload the changed vertex colors to the Mesh.
    99.             m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    100.  
    101.             if (currentCharacter + 1 < characterCount) currentCharacter += 1;
    102.  
    103.             yield return new WaitForSeconds(0.25f - FadeSpeed * 0.01f);
    104.         }
    105.     }
    106.  
    107. }
    108.  
    Hope this helps.
     
    a52, UnrealSoftware, vozcn and 3 others like this.
  9. respectyoda

    respectyoda

    Joined:
    Apr 27, 2018
    Posts:
    11
    This code works great with one exception. When the loop finishes fading in every letter in the paragraph, the text disappears. (Note: the isRangeMax = true; line is not commented out). I want the text to stay opaque once the loop is over. I tried to modify the code to make this work but nothing is quite working.

    EDIT: Got it working!
     
    Last edited: Sep 4, 2021
    Ranger-Ori likes this.
  10. Ranger-Ori

    Ranger-Ori

    Joined:
    Apr 29, 2010
    Posts:
    29

    Hey,

    Do you mind sharing what you did to make it stop? and not loop?
     
  11. Ninja_Coder

    Ninja_Coder

    Joined:
    Dec 31, 2012
    Posts:
    5
    To stop looping
    remove the Slash "//"

    Code (CSharp):
    1.  
    2. //isRangeMax = true;
    3.  
    4. into
    5.  
    6. isRangeMax = true;
    7.  
    8.  
     
    MatanYamin and vozcn like this.
  12. mikameel

    mikameel

    Joined:
    Sep 22, 2021
    Posts:
    1
    So I wanted to be able to change if the text should be fading yes or not.

    This will activate the loop on Trigger, and deactivate the loop on Trigger. It also makes sure that when the loop exits the text is not transparent. Before this, the text would disappear on exiting the loop.


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using TMPro;
    4. using UnityEngine;
    5.  
    6. public class TextFade : MonoBehaviour
    7. {
    8.     [SerializeField] private TextMeshPro m_TextComponent;
    9.     [SerializeField] private float FadeSpeed = 20.0f;
    10.     [SerializeField] private int RolloverCharacterSpread = 10;
    11.     public bool FadeActiveTrigger = false;
    12.     public bool FadeNotActiveTrigger = false;
    13.  
    14.     private bool isFading = false;
    15.  
    16.  
    17.     void Start()
    18.     {
    19.      
    20.     }
    21.  
    22.     private void Update()
    23.     {
    24.         if (FadeActiveTrigger)
    25.         {
    26.             isFading = true;
    27.             StartCoroutine(FadeInText());
    28.             FadeActiveTrigger = false;
    29.         }
    30.  
    31.         if (FadeNotActiveTrigger)
    32.         {
    33.             StopCoroutine(FadeInText());
    34.             FadeNotActiveTrigger = false;
    35.             isFading = false;
    36.         }
    37.     }
    38.  
    39.  
    40.     /// <summary>
    41.     /// Method to animate (fade in) vertex colors of a TMP Text object.
    42.     /// </summary>
    43.     /// <returns></returns>
    44.     IEnumerator FadeInText()
    45.     {
    46.      
    47.      
    48.      
    49.         // Set the whole text transparent
    50.         m_TextComponent.color = new Color
    51.             (
    52.                 m_TextComponent.color.r,
    53.                 m_TextComponent.color.g,
    54.                 m_TextComponent.color.b,
    55.                 0
    56.             );
    57.         // Need to force the text object to be generated so we have valid data to work with right from the start.
    58.         m_TextComponent.ForceMeshUpdate();
    59.  
    60.  
    61.         TMP_TextInfo textInfo = m_TextComponent.textInfo;
    62.         Color32[] newVertexColors;
    63.  
    64.         int currentCharacter = 0;
    65.         int startingCharacterRange = currentCharacter;
    66.         bool isRangeMax = false;
    67.  
    68.         while (!isRangeMax && isFading)
    69.         {
    70.             int characterCount = textInfo.characterCount;
    71.  
    72.             // Spread should not exceed the number of characters.
    73.             byte fadeSteps = (byte)Mathf.Max(1, 255 / RolloverCharacterSpread);
    74.  
    75.             for (int i = startingCharacterRange; i < currentCharacter + 1; i++)
    76.             {
    77.                 // Skip characters that are not visible (like white spaces)
    78.                 if (!textInfo.characterInfo[i].isVisible) continue;
    79.  
    80.                 // Get the index of the material used by the current character.
    81.                 int materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
    82.  
    83.                 // Get the vertex colors of the mesh used by this text element (character or sprite).
    84.                 newVertexColors = textInfo.meshInfo[materialIndex].colors32;
    85.  
    86.                 // Get the index of the first vertex used by this text element.
    87.                 int vertexIndex = textInfo.characterInfo[i].vertexIndex;
    88.  
    89.                 // Get the current character's alpha value.
    90.                 byte alpha = (byte)Mathf.Clamp(newVertexColors[vertexIndex + 0].a + fadeSteps, 0, 255);
    91.  
    92.                 // Set new alpha values.
    93.                 newVertexColors[vertexIndex + 0].a = alpha;
    94.                 newVertexColors[vertexIndex + 1].a = alpha;
    95.                 newVertexColors[vertexIndex + 2].a = alpha;
    96.                 newVertexColors[vertexIndex + 3].a = alpha;
    97.  
    98.                 if (alpha == 255)
    99.                 {
    100.                     startingCharacterRange += 1;
    101.  
    102.                     if (startingCharacterRange == characterCount)
    103.                     {
    104.                         // Update mesh vertex data one last time.
    105.                         m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    106.  
    107.                         yield return new WaitForSeconds(1.0f);
    108.  
    109.                         // Reset the text object back to original state.
    110.                         m_TextComponent.ForceMeshUpdate();
    111.  
    112.                         yield return new WaitForSeconds(1.0f);
    113.  
    114.                         // Reset our counters.
    115.                         currentCharacter = 0;
    116.                         startingCharacterRange = 0;
    117.                         //isRangeMax = true; // Would end the coroutine.
    118.                     }
    119.                 }
    120.             }
    121.  
    122.             // Upload the changed vertex colors to the Mesh.
    123.             m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    124.  
    125.             if (currentCharacter + 1 < characterCount) currentCharacter += 1;
    126.  
    127.             yield return new WaitForSeconds(0.25f - FadeSpeed * 0.01f);
    128.         }
    129.  
    130.         if (!isFading)
    131.         {
    132.             m_TextComponent.color = new Color(m_TextComponent.color.r, m_TextComponent.color.g, m_TextComponent.color.b, 1);
    133.             m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    134.         }
    135.     }
    136.  
    137. }
    138.  
    Please let me know if you find any way to improve, or if you have better solutions.