Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug First character got flicker when change other characters vertex alpha

Discussion in 'UGUI & TextMesh Pro' started by SolarianZ, Jul 26, 2021.

  1. SolarianZ

    SolarianZ

    Joined:
    Jun 13, 2017
    Posts:
    229
    I am trying to implement a typewriter effect with characters fade in, but when I change the vertex alpha of characters, the first character of TextMeshProUGUI always got flicker. Is this a bug? Or I need to modify my code in some way?

    upload_2021-7-26_19-15-22.gif

    Code (CSharp):
    1. [RequireComponent(typeof(TMP_Text))]
    2. public class TypewriterWithFading : MonoBehaviour
    3. {
    4.     [Tooltip("Character output speed(character per second).")]
    5.     [Range(1, 255)]
    6.     public byte OutputSpeed = 20;
    7.  
    8.     [Tooltip("Character fade in range.")]
    9.     [Range(0, 50)]
    10.     public int FadeRange = 10;
    11.  
    12.     private TMP_Text _textComponent;
    13.  
    14.  
    15.     private void Start()
    16.     {
    17.         _textComponent = GetComponent<TMP_Text>();
    18.         StartCoroutine(OutputCharactersFading());
    19.     }
    20.  
    21.     private IEnumerator OutputCharactersFading()
    22.     {
    23.         _textComponent.ForceMeshUpdate();
    24.  
    25.         // end output if no character
    26.         var textInfo = _textComponent.textInfo;
    27.         if (textInfo.characterCount == 0)
    28.         {
    29.             yield break;
    30.         }
    31.  
    32.         // set all characters transparent
    33.         for (int i = 0; i < textInfo.characterCount; i++)
    34.         {
    35.             SetCharacterAlpha(i, 0);
    36.         }
    37.  
    38.         // fade in characters by time
    39.         var timer = 0f;
    40.         var interval = 1.0f / OutputSpeed;
    41.         var headCharacterIndex = 0;
    42.         while (true)
    43.         {
    44.             timer += Time.deltaTime;
    45.  
    46.             // calc vertex alpha
    47.             var isFadeCompleted = true;
    48.             var tailIndex = headCharacterIndex - FadeRange + 1;
    49.             for (int i = headCharacterIndex; i > -1 && i >= tailIndex; i--)
    50.             {
    51.                 var step = headCharacterIndex - i;
    52.                 var alpha = (byte)Mathf.Clamp((timer / interval + step) / FadeRange * 255, 0, 255);
    53.  
    54.                 isFadeCompleted &= alpha == 255;
    55.                 SetCharacterAlpha(i, alpha);
    56.             }
    57.  
    58.             _textComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    59.  
    60.             // check if output is completed
    61.             if (timer >= interval)
    62.             {
    63.                 if (headCharacterIndex < textInfo.characterCount - 1)
    64.                 {
    65.                     timer = 0;
    66.                     headCharacterIndex++;
    67.                 }
    68.                 else if (isFadeCompleted)
    69.                 {
    70.                     yield break;
    71.                 }
    72.             }
    73.  
    74.             yield return null;
    75.         }
    76.     }
    77.  
    78.     private void SetCharacterAlpha(int index, byte alpha)
    79.     {
    80.         var materialIndex = _textComponent.textInfo.characterInfo[index].materialReferenceIndex;
    81.         var vertexColors = _textComponent.textInfo.meshInfo[materialIndex].colors32;
    82.         var vertexIndex = _textComponent.textInfo.characterInfo[index].vertexIndex;
    83.  
    84.         vertexColors[vertexIndex + 0].a = alpha;
    85.         vertexColors[vertexIndex + 1].a = alpha;
    86.         vertexColors[vertexIndex + 2].a = alpha;
    87.         vertexColors[vertexIndex + 3].a = alpha;
    88.     }
    89. }
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    When iterating over characterInfo, you have to exclude non visible characters since they have no geometry.

    As such, the vertexIndex of those non visible characters would be zero which happens to be the same as the first character.
     
    SolarianZ likes this.
  3. SolarianZ

    SolarianZ

    Joined:
    Jun 13, 2017
    Posts:
    229
    Thank you! That worked!