Search Unity

TextMesh Pro [3.0.6] TextInfo has incorrect character vertex info when using <font> tags

Discussion in 'UGUI & TextMesh Pro' started by Brody-TOG, Feb 5, 2022.

  1. Brody-TOG

    Brody-TOG

    Joined:
    May 7, 2020
    Posts:
    15
    In my project, I'm doing a bunch of stuff with modifying the mesh data of characters to do things like bouncing/rotating/scaling text. This has been going great, modifying textObject.mesh.vertices while figuring out which vertices I need to modify with textMeshObject.textInfo.characterInfo.vertexIndex and this works reliably.

    Then I hit a peculiar problem with I started adding formatting such as the <font="other font"> tag. Suddenly, every other character besides the ones I actually want to modify were being affected. I can't seem to pinpoint what's at play here but I suspect the information I'm getting back from textInfo is render obsolete when doing the font change?

    Test Script:
    To use: attach this component to a TextMeshPro - Text object and enter Play Mode. The word HAMBURGER should be bobbing up and down. Next, wrap some text in the text field in a valid <font> tag like so:

    I'M A <font="Lavanderia Sturdy SDF">HAMBURGER</font> PATTY

    Notice that all text besides the text wrapped in the <font> tag is bobbing now.

    Code (CSharp):
    1. using TMPro;
    2. using UnityEngine;
    3.  
    4. public sealed class TextMeshModifyTest : MonoBehaviour
    5. {
    6.     #region Members
    7.     [SerializeField] private string text = "I'M A HAMBURGER PATTY";
    8.     [SerializeField] private Vector2Int range = new Vector2Int(5, 14);
    9.     [SerializeField] private float bobAmplitude = 0.25f;
    10.     [SerializeField] private float bobFrequency = 10f;
    11.  
    12.     private TextMeshPro textObject;
    13.     private float bobProgress;
    14.     private Vector3[] originalVertices;
    15.     private Vector3[] modifiedVertices;
    16.     #endregion
    17.  
    18.     #region MonoBehaviour Methods
    19.     private void Awake ()
    20.     {
    21.         textObject = GetComponent<TextMeshPro>();
    22.        
    23.         if (textObject == null)
    24.             return;
    25.        
    26.         textObject.SetText(text);
    27.         textObject.ForceMeshUpdate();
    28.         CacheCharacterData();
    29.     }
    30.  
    31.     private void Update ()
    32.     {
    33.         if (textObject == null)
    34.             return;
    35.        
    36.         ResetModifiedVertices();
    37.  
    38.         bobProgress += Time.deltaTime * bobFrequency;
    39.         float verticalOffset = Mathf.Sin(bobProgress) * bobAmplitude;
    40.  
    41.         for (int i = range.x; i <= range.y; ++i)
    42.         {
    43.             if (i < 0 || i >= textObject.textInfo.characterCount)
    44.                 continue;
    45.  
    46.             TMP_CharacterInfo charInfo = textObject.textInfo.characterInfo[i];
    47.  
    48.             if (!charInfo.isVisible)
    49.                 continue;
    50.  
    51.             int vertexIndex = charInfo.vertexIndex;
    52.            
    53.             Vector3 offset = verticalOffset * Vector3.up;
    54.             modifiedVertices[vertexIndex] += offset;
    55.             modifiedVertices[vertexIndex + 1] += offset;
    56.             modifiedVertices[vertexIndex + 2] += offset;
    57.             modifiedVertices[vertexIndex + 3] += offset;
    58.         }
    59.        
    60.         ApplyModifiedVertices();
    61.     }
    62.     #endregion
    63.  
    64.     #region Text Methods
    65.     private void CacheCharacterData ()
    66.     {
    67.         originalVertices = textObject.mesh.vertices;
    68.         modifiedVertices = textObject.mesh.vertices;
    69.     }
    70.  
    71.     private void ResetModifiedVertices ()
    72.     {
    73.         if (originalVertices == null)
    74.             return;
    75.  
    76.         if (modifiedVertices == null || modifiedVertices.Length != originalVertices.Length)
    77.         {
    78.             modifiedVertices = new Vector3[originalVertices.Length];
    79.             System.Array.Copy(originalVertices, modifiedVertices, originalVertices.Length);
    80.             return;
    81.         }
    82.  
    83.         int i = 0;
    84.         for (i = 0; i < originalVertices.Length; ++i)
    85.         {
    86.             modifiedVertices[i].x = originalVertices[i].x;
    87.             modifiedVertices[i].y = originalVertices[i].y;
    88.             modifiedVertices[i].z = originalVertices[i].z;
    89.         }
    90.     }
    91.    
    92.     private void ApplyModifiedVertices ()
    93.     {
    94.         if (ReferenceEquals(textObject, null) || modifiedVertices == null || modifiedVertices.Length == 0)
    95.             return;
    96.  
    97.         textObject.mesh.vertices = modifiedVertices;
    98.        
    99.         // Push changes into meshes
    100.         for (int i = 0; i < textObject.textInfo.meshInfo.Length; i++)
    101.         {
    102.             textObject.UpdateGeometry(textObject.textInfo.meshInfo[i].mesh, i);
    103.         }
    104.     }
    105.     #endregion
    106. }
    Other Info:
    - Unity 2021.2.8f1
    - TextMesh Pro 3.0.6
     
  2. Brody-TOG

    Brody-TOG

    Joined:
    May 7, 2020
    Posts:
    15
    If I'm taking the wrong approach here, I'd really like to know. This has been vexing me for a while now! :(