Search Unity

TextMesh Pro Changing fonts at runtime with TextMeshPro yields garbage

Discussion in 'UGUI & TextMesh Pro' started by RChanlatte, Nov 17, 2022.

  1. RChanlatte

    RChanlatte

    Joined:
    Oct 4, 2022
    Posts:
    3
    Hey yall. Does anyone have any insight into the appropriate way to change TextMeshPro fonts at runtime in C#? I read the docs and set it up, but when I do it the text is garbled on font/material change.

    Here is a video of what I mean using a small example project.

    Of interest is that the corruption is super inconsistent. Sometimes the font will change fine, but modifying a shader property (such as the outline size) will cause the corruption. Other instances will work properly regardless of property modification, and other times it will corrupt instantly (as shown in the video). Builds are, in general, more stable though the corruption can be goaded out if you mess around with it enough. Would appreciate any insight from anyone who thinks they can help.

    Here is also the code that is being used in that video:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using TMPro;
    4.  
    5. public class MyFontPropertyChangeBug : MonoBehaviour
    6. {
    7.     #region Inspector
    8.  
    9.     float prevTxtSz = 0.0f;
    10.     public float fontSzOffset = 0.0f;
    11.  
    12.     float prevOutlineSz = 0.0f;
    13.     public float outlineSzOffset = 0.0f;
    14.  
    15.     TextMeshProUGUI[] UiTxt;
    16.     float[] TxtBaseSzs;
    17.     const float outlineBaseSz = 0.15f;
    18.     bool usingDysFont = false;
    19.  
    20.     [Header("Font Manipulation Buttons")]
    21.     public Button changeFontBtn;
    22.     public Slider FontSizeSldr;
    23.     public Slider OutlineSizeSldr;
    24.  
    25.     [Header("Fonts")]
    26.     public TMP_FontAsset baseFont;
    27.     public Material baseFontMat;
    28.  
    29.     public TMP_FontAsset DyslexicFont;
    30.     public Material DyslexicFontMat;
    31.  
    32.     #endregion
    33.  
    34.     public void SlideTxtSz(float fontSz)
    35.     {
    36.         fontSzOffset = fontSz;
    37.         float newOffset = fontSz - prevTxtSz;
    38.         prevTxtSz = fontSz;
    39.  
    40.         for(int i = 0, len = UiTxt.Length; i < len; ++i)
    41.         {
    42.             UiTxt[i].fontSize += newOffset;
    43.         }
    44.     }
    45.  
    46.     public void SlideOutlineSz(float inputOutlineSz)
    47.     {
    48.         outlineSzOffset = inputOutlineSz;
    49.         float newOffset = inputOutlineSz - prevOutlineSz;
    50.         prevOutlineSz = inputOutlineSz;
    51.  
    52.         for (int i = 0, len = UiTxt.Length; i < len; ++i)
    53.         {
    54.             UiTxt[i].outlineWidth += newOffset;
    55.         }
    56.     }
    57.  
    58.     public void ChangeFont()
    59.     {
    60.         usingDysFont = !usingDysFont;
    61.        
    62.         float newOutline = outlineBaseSz + outlineSzOffset;
    63.         if (usingDysFont == false)
    64.         {
    65.             for (int i = 0, len = UiTxt.Length; i < len; ++i)
    66.             {
    67.                 if (UiTxt[i] != null)
    68.                 {
    69.                     UiTxt[i].font = baseFont;
    70.                     UiTxt[i].fontSharedMaterial = baseFontMat;
    71.                     UiTxt[i].fontSize = TxtBaseSzs[i] + fontSzOffset;
    72.                     UiTxt[i].outlineWidth = newOutline;
    73.                     UiTxt[i].ForceMeshUpdate(true);
    74.                 }
    75.             }
    76.         }
    77.         else
    78.         {
    79.             for (int i = 0, len = UiTxt.Length; i < len; ++i)
    80.             {
    81.                 if (UiTxt[i] != null)
    82.                 {
    83.                     UiTxt[i].font = DyslexicFont;
    84.                     UiTxt[i].fontSharedMaterial = DyslexicFontMat;
    85.                     UiTxt[i].fontSize = TxtBaseSzs[i] + fontSzOffset;
    86.                     UiTxt[i].outlineWidth = newOutline;
    87.                     UiTxt[i].ForceMeshUpdate(true);
    88.                 }
    89.             }
    90.         }
    91.     }
    92.  
    93.     public void FetchTMPandProperties()
    94.     {
    95.         UiTxt = GetComponentsInChildren<TextMeshProUGUI>();
    96.         int TMPCt = UiTxt.Length;
    97.  
    98.         TxtBaseSzs = new float[TMPCt];
    99.         for (int i = 0; i < TMPCt; ++i)
    100.         {
    101.             TxtBaseSzs[i] = UiTxt[i].fontSize;
    102.         }
    103.     }
    104.  
    105.     void Start()
    106.     {
    107.         FetchTMPandProperties();
    108.         changeFontBtn.onClick.AddListener(ChangeFont);
    109.         FontSizeSldr.onValueChanged.AddListener(SlideTxtSz);
    110.         OutlineSizeSldr.onValueChanged.AddListener(SlideOutlineSz);
    111.     }
    112. }
     

    Attached Files:

  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
  3. RChanlatte

    RChanlatte

    Joined:
    Oct 4, 2022
    Posts:
    3
    Thanks, that was it.

    For future Googlers/Readers (more likely me when I forget why): Modifying the outline width in that manner created a material instance that, while updating the outline width, overwrote the font with the old one causing the glyphs to render incorrectly. So, for people who have this glyph render issue, double check you are modifying your materials correctly.