Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We've updated our Terms of Service. Please read our blog post from Unity CTO and Co-Founder Joachim Ante here
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

TextMesh Pro Teletype interfering with Vertex Jitter

Discussion in 'Unity UI & TextMesh Pro' started by hoperin, Jan 11, 2019.

  1. hoperin

    hoperin

    Joined:
    Feb 9, 2014
    Posts:
    38
    I'm trying to figure out how to get something to work that I'm sure other people must have tried to accomplish, but that I haven't seen any solutions for -- teletyping with vertexjitter effects. All our text is using Teletype, where the core code is

    m_textMeshPro.maxVisibleCharacters = visibleCount;

    When I try to add on an effect that modifies the vertexes ie the VertexJitter example included w TMPro, I get a very jagged, janky effect where it sort of jitters while it types, but its clear once it finishes typing and jitters properly that it was not behaving as it should.

    https://forum.unity.com/threads/typewriter-jitter-and-wave-effects-at-once.532184/ This thread makes it clear that the issue is that when changing .maxVisibleCharacters, the vertexes are reset. My own testing has confirmed this -- when i drastically slow down my Teletype update speed, the issue is undetectable. Ideally one could just make it not do this reset behaviour, but I can't figure out where to get at that.

    I thought that if I saved the vertex info everytime Jitter updated, and forced that saved vertex info back in after each maxVisibleCharacter change, I could override the vertex reset that happens after maxVisibleCharacter, but no such luck.

    https://imgur.com/liQpPCZ Here's a 60fps gif of the behaviour I'm getting.

    I had hoped it wouldn't be this tricky to get vertex effects working alongside a teletype effect. Any help greatly appreciated.

    VertexJitter Snippet:
    Code (CSharp):
    1. // Push changes into meshes
    2.                 for (int i = 0; i < textInfo.meshInfo.Length; i++)
    3.                 {
    4.                     textInfo.meshInfo[i].mesh.vertices = textInfo.meshInfo[i].vertices;
    5.                     m_TextComponent.UpdateGeometry(textInfo.meshInfo[i].mesh, i);
    6.  
    7.  
    8.                 }
    9.  
    10.                 PublicMeshInfo = textInfo.meshInfo;
    Teletype Snippet:
    Code (CSharp):
    1. while (reading && m_textMeshPro.maxVisibleCharacters != m_textMeshPro.textInfo.characterCount)
    2.             {
    3.  
    4.                 if (!Mgr_PlayState.Instance.Paused){
    5.  
    6.                     visibleCount += 1;
    7.  
    8.                     //this is the problem point...
    9.                     m_textMeshPro.maxVisibleCharacters = visibleCount; // How many characters should TextMeshPro display?
    10.  
    11.                     //try to update back to the vertex
    12.                     for (int i = 0; i < m_textMeshPro.textInfo.meshInfo.Length; i++)
    13.                     {
    14.                          m_textMeshPro.textInfo.meshInfo[i].mesh.vertices = this.GetComponent<VertexJitter>().PublicMeshInfo[i].vertices;
    15.                          m_textMeshPro.UpdateGeometry(m_textMeshPro.textInfo.meshInfo[i].mesh, i);
    16.                     }
    17.                     m_textMeshPro.ForceMeshUpdate();
    18.  
    19.                     // Once the last character has been revealed, wait 1.0 second and start over.
    20.                     if (visibleCount >= totalVisibleCharacters)
    21.                     {
    22.                         ShowAllText();
    23.                     }
    24.              
    25.                 }
    26.  
    27.                 yield return new WaitForSeconds(textReadSpeed);
    28.  
    29.             }
     
  2. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    1,991
    Since you are already having to iterate over each of the characters to add the Jitter, I would suggest controlling the visibility of each character in the same fashion instead of using .maxVisibleCharacters which ends up forcing a regeneration of the text object which in turn resets the geometry.

    In other words, as you iterate over (only the visible) characters, to add the Jitter FX also control their vertex color alpha to do the Teletype FX. Since this won't be setting the text object dirty, it won't reset the geometry.

    See the following post which is another example of sort of a Teletype FX with color.

    See the following post which might prove helpful.
     
  3. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    1,991
    In case, you can't see that post on the old TMP user forum. This is an old post so some of the code might need tweaks but the idea remains the same.

    Here is an example where the text is faded per character with control over the number of characters the fade occurs over + tint control.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. namespace TMPro.Examples
    5. {
    6.     public class RollingTextFade : MonoBehaviour
    7.     {
    8.         private TMP_Text m_TextComponent;
    9.         public float FadeSpeed = 1.0F;
    10.         public int RolloverCharacterSpread = 10;
    11.         public Color ColorTint;
    12.         void Awake()
    13.         {
    14.             m_TextComponent = GetComponent<TMP_Text>();
    15.         }
    16.         void Start()
    17.         {
    18.             StartCoroutine(AnimateVertexColors());
    19.         }
    20.         /// <summary>
    21.         /// Method to animate vertex colors of a TMP Text object.
    22.         /// </summary>
    23.         /// <returns></returns>
    24.         IEnumerator AnimateVertexColors()
    25.         {
    26.             // Need to force the text object to be generated so we have valid data to work with right from the start.
    27.             m_TextComponent.ForceMeshUpdate();
    28.             TMP_TextInfo textInfo = m_TextComponent.textInfo;
    29.             Color32[] newVertexColors;
    30.             int currentCharacter = 0;
    31.             int startingCharacterRange = currentCharacter;
    32.             bool isRangeMax = false;
    33.             while (!isRangeMax)
    34.             {
    35.                 int characterCount = textInfo.characterCount;
    36.                 // Spread should not exceed the number of characters.
    37.                 byte fadeSteps = (byte)Mathf.Max(1, 255 / RolloverCharacterSpread);
    38.                 for (int i = startingCharacterRange; i < currentCharacter + 1; i++)
    39.                 {
    40.                     // Skip characters that are not visible
    41.                     if (!textInfo.characterInfo[i].isVisible) continue;
    42.                     // Get the index of the material used by the current character.
    43.                     int materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
    44.                     // Get the vertex colors of the mesh used by this text element (character or sprite).
    45.                     newVertexColors = textInfo.meshInfo[materialIndex].colors32;
    46.                     // Get the index of the first vertex used by this text element.
    47.                     int vertexIndex = textInfo.characterInfo[i].vertexIndex;
    48.                     // Get the current character's alpha value.
    49.                     byte alpha = (byte)Mathf.Clamp(newVertexColors[vertexIndex + 0].a - fadeSteps, 0 , 255);
    50.                     // Set new alpha values.
    51.                     newVertexColors[vertexIndex + 0].a = alpha;
    52.                     newVertexColors[vertexIndex + 1].a = alpha;
    53.                     newVertexColors[vertexIndex + 2].a = alpha;
    54.                     newVertexColors[vertexIndex + 3].a = alpha;
    55.                     // Tint vertex colors
    56.                     // Note: Vertex colors are Color32 so we need to cast to Color to multiply with tint which is Color.
    57.                     newVertexColors[vertexIndex + 0] = (Color)newVertexColors[vertexIndex + 0] * ColorTint;
    58.                     newVertexColors[vertexIndex + 1] = (Color)newVertexColors[vertexIndex + 1] * ColorTint;
    59.                     newVertexColors[vertexIndex + 2] = (Color)newVertexColors[vertexIndex + 2] * ColorTint;
    60.                     newVertexColors[vertexIndex + 3] = (Color)newVertexColors[vertexIndex + 3] * ColorTint;
    61.                     if (alpha == 0)
    62.                     {
    63.                         startingCharacterRange += 1;
    64.                         if (startingCharacterRange == characterCount)
    65.                         {
    66.                             // Update mesh vertex data one last time.
    67.                             m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    68.                             yield return new WaitForSeconds(1.0f);
    69.                             // Reset the text object back to original state.
    70.                             m_TextComponent.ForceMeshUpdate();
    71.                             yield return new WaitForSeconds(1.0f);
    72.                             // Reset our counters.
    73.                             currentCharacter = 0;
    74.                             startingCharacterRange = 0;
    75.                             //isRangeMax = true; // Would end the coroutine.
    76.                         }
    77.                     }
    78.                 }
    79.                 // Upload the changed vertex colors to the Mesh.
    80.                 m_TextComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
    81.                 if (currentCharacter + 1 < characterCount) currentCharacter += 1;
    82.                 yield return new WaitForSeconds (0.25f - FadeSpeed * 0.01f);
    83.             }
    84.         }
    85.     }
    86. }
    87.  
     
    hoperin likes this.