Search Unity

TextMesh Pro Trouble programatically changing Text Mesh Pro font.

Discussion in 'UGUI & TextMesh Pro' started by StrawberryJellyfish, May 9, 2017.

  1. StrawberryJellyfish

    StrawberryJellyfish

    Joined:
    Oct 29, 2016
    Posts:
    23
    Hello everyone. I'm introducing localization into my game, and I;m running into trouble when I try to programatically change the font of a Text Mesh Pro asset when a button is pressed. This is the script:

    Code (CSharp):
    1. public TMP_FontAsset normalFontTMP, russianFontTMP;
    2.      public void localize () {
    3.      textMeshPro.text = LocalizationText.GetText(key);
    4.      if (LocalizationText.GetLanguage().Equals("RU"))
    5.      {
    6.          Debug.Log("Russian");
    7.          textMeshPro.font = russianFontTMP;
    8.          textMeshPro.fontSharedMaterial = russianFontTMP.material;
    9.      }
    10.      else
    11.      {
    12.          Debug.Log("NOrmal");
    13.          textMeshPro.font = normalFontTMP;
    14.          textMeshPro.fontSharedMaterial = normalFontTMP.material;
    15.      }
    16. }`
    The font or text doesn't update until the Text Mesh Pro's object is disabled and re-enabled. I'm not entirely sure if I'm doing this correctly. Could someone pleas offer some assistance?
     
    makaka-org likes this.
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Unless you want to use a different material preset than the default material of the font asset, you don't need to assign a new material. Assigning a new font asset will take care of also changing the material preset.

    There could be something else going on with your script / implementation that is affecting this.

    Here is a simple script which will switch font asset and in this case use a different material preset for both fonts.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using TMPro;
    6.  
    7. public class SandBox_32 : MonoBehaviour
    8. {
    9.     public TMP_FontAsset FontAssetA;
    10.     public TMP_FontAsset FontAssetB;
    11.  
    12.     public Material FontMaterialA;
    13.     public Material FontMaterialB;
    14.  
    15.     private TMP_Text m_TextComponent;
    16.  
    17.  
    18.     private void Awake()
    19.     {
    20.         m_TextComponent = GetComponent<TMP_Text>();
    21.     }
    22.  
    23.  
    24.     IEnumerator Start()
    25.     {
    26.         // Assign the new font asset.
    27.         m_TextComponent.font = FontAssetA;
    28.  
    29.         // Use a different material preset which was derived from this font asset and created using the Create Material Preset Context Menu.
    30.         m_TextComponent.fontSharedMaterial = FontMaterialA;
    31.  
    32.         yield return new WaitForSeconds(2.0f);
    33.  
    34.         m_TextComponent.font = FontAssetB;
    35.         m_TextComponent.fontSharedMaterial = FontMaterialB;
    36.     }
    37. }
    38.  
     
    Knarhoi and PEZO19 like this.
  3. StrawberryJellyfish

    StrawberryJellyfish

    Joined:
    Oct 29, 2016
    Posts:
    23
    Thanks for the explanation. I made the changes, and upon further investigation I understand some of the other errors I was getting in the logger.
     
    Last edited: May 9, 2017
  4. makaka-org

    makaka-org

    Joined:
    Dec 1, 2013
    Posts:
    1,026
    Hi, @Stephan_B , your help will be appreciated. In my case, I want next with world space text.
    1. In runtime, I want to customize (with help of GUI) font main settings (font size, color...) and font material settings (outline color & outline thickness) - no problem with it.
    2. Next, I want to save the changes/state of the whole text somehow.
      1. Material settings can be saved by creating material from the current font material & assigning it to the fontSharedMaterial. But this doesn't work. Why? I don't want to change the font asset itself.
      2. Font Main Settings can be saved from serialization/derealization, I guess, but I didn't make an investigation in it. So, any tips will be helpful, if you know other ways or examples.
    3. Apply the changes/state to other text game objects in world space that uses the same font/material.
    Environment:
    • TextMesh PRO 2.1.3
    • Unity 2019.4.18
     
  5. Allthebees

    Allthebees

    Joined:
    Apr 22, 2017
    Posts:
    18
    Hi Stephan, hope you had a good weekend.

    I've found an issue when changing fonts programmatically while also trying to change the outline color directly afterwards.

    The font will change, however, setting the outline color, will set the outline of the previous font's material. This causes the Text Mesh Pro component to switch back to the old font's material and render incorrectly, like so:

    upload_2021-3-8_10-56-27.png

    You can fix this in the inspector by altering the text or even reselecting the current Material in the Material Preset drop-down list. But this leaves you with the correct font, and the default (incorrect) outline color. I have not been able to find a solution that will work at run-time unfortunately, which means I can't fix the issue for my game :(

    I tried delaying the point at which I would set the outline color of the text. This does not seem to resolve the issue as the reference to the outline color is still using the old font's material if I grab it in the same method (after setting the new font).

    It's a little tricky to send an example but I'll work on creating a test project later today:

    Found here: shorturl.at/atDL2

    The forum won't let me hyperlink due to spam blocking
     
    Last edited: Mar 8, 2021
  6. ExNinja

    ExNinja

    Joined:
    Dec 4, 2013
    Posts:
    30
    August 6, 2023 – Update, Fix, and Potential Bug Discovered

    An update on a bug I found while working through this issue. In my case, I'm swapping two very different fonts for the same characters (an English and an Aurebesh (Star Wars) font). To do this, I have prefabs that have the correct TextMeshPro settings for each place that I use the different fonts (I have different settings for how the font should look on a button vs. another part of the UI). I use these prefabs as an example and then copy the important settings from them to the "target" TMP_Text Component. Here is my code to do so:

    Code (CSharp):
    1.         static public void CopyTMP_TextInfo( TMP_Text example, TMP_Text target ) {
    2.             if ( target == null || example == null ) return;
    3.  
    4.             string txt = target.text;
    5.             target.gameObject.SetActive( false );
    6.             target.enabled = false;
    7.            
    8.             target.font = example.font;
    9.             target.fontSharedMaterial = example.fontSharedMaterial;
    10.             target.faceColor = example.faceColor;
    11.             target.outlineColor = example.outlineColor;
    12.             target.outlineWidth = example.outlineWidth;
    13.             target.fontSize = example.fontSize;
    14.             target.fontWeight = example.fontWeight;
    15.             target.characterSpacing = example.characterSpacing;
    16.             target.fontStyle = example.fontStyle;
    17.  
    18.  
    19.             target.text = "";
    20.             target.text = txt; // Possibly reset the rendering of the mesh
    21.             target.ForceMeshUpdate(true, true);
    22.            
    23.             target.enabled = true;
    24.             target.gameObject.SetActive( true );
    25.         }
    Note that I'm using several tricks mentioned above, including enabling and disabling the TMP_Text component, setting text to "" and then setting it back, and setting the gameObject to be inactive and then active. I have not experimented to see which (if any) of these are actually required.

    The new thing that I did find is that TextMeshPro will not correctly copy over Material Preset settings from the automatically-created version of the Material Preset. When using example TMP_Text fields that used the default Material Preset, outlines were broken, and other aspects of the fontSharedMaterial just didn't work. On the other hand, if I manually create a Material Preset (see image below) and assign it to the example TMP_Text Component, then the fontSharedMaterial settings do copy over to the target TMP_Text instance correctly.

    upload_2023-8-6_22-25-46.png
     
    xucian likes this.