Search Unity

TextMesh Pro Speed Problem

Discussion in 'UGUI & TextMesh Pro' started by unity_P6mxp0LUvUdvoA, Jun 13, 2019.

  1. unity_P6mxp0LUvUdvoA

    unity_P6mxp0LUvUdvoA

    Joined:
    Sep 11, 2018
    Posts:
    5
    Hello,

    I just recently converted our product to use TextMesh Pro, and am noticing some significant UI slowdowns, particularly in our chat window, which is optionally shown and hidden by clicking a button. When profiling, I noticed that the problem is that TextMeshProUGUI components have an OnEnable call, and we have multiple text components for each chat message. The OnEnable calls seem to take .32ms each, which can add up quite quickly. Is there any way to avoid the expense of the OnEnable call or just remove the call altogether?

    See image for what we're seeing.
     

    Attached Files:

  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Make sure you are testing in a build as there is additional overhead in the Editor.

    Enabling / Disabling UI objects that are using Layout Components or affected by Layout components will trigger a rebuild of the layout which has performance overhead.

    In order to provide additional insight, I would need a better understanding of the hierarchy of these scene objects and if they are affected by Layout components.
     
  3. unity_P6mxp0LUvUdvoA

    unity_P6mxp0LUvUdvoA

    Joined:
    Sep 11, 2018
    Posts:
    5
    Hello,

    I was able to get more detailed information using the deep profiler. It seems that TMP_Text.ParseInputText took 113ms to rerender its canvas, which is really expensive. Seems like most of the time is spent loading the font using FontEngine.LoadFontFace(43ms), which is crazy to have to call every time we disable->enable a script object.

    Please see the attached deep profiling session.
     

    Attached Files:

  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    This specific performance issue has already been addressed. See the following post for more details. The changes will be included in the next release of the TMP package which will be version 1.4.2 for Unity 2018.4 and 2.0.2 for Unity 2019.x.
     
  5. unity_P6mxp0LUvUdvoA

    unity_P6mxp0LUvUdvoA

    Joined:
    Sep 11, 2018
    Posts:
    5
    Awesome, thanks. Is there any way around this for now, or an eta on the next release? Hoping to get a fix for this soon.
     
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Making the following changes to the TMP_FontAsset.cs will help but is only part of the changes.

    upload_2019-6-13_16-11-29.png

    This change will make it so that TMP doesn't try to add a character / glyph that is already known to be missing. This should help.

    In terms of the next release, maybe within the next 10 days. I need to get the core changes to land in Unity first since the changes to the FontEngine are in Unity itself and not the TMP package.
     
  7. unity_P6mxp0LUvUdvoA

    unity_P6mxp0LUvUdvoA

    Joined:
    Sep 11, 2018
    Posts:
    5
    Thank you so much! That's exactly what I was looking for. Will be looking forward to the update in 10 days.

    I had one more quick question: Do you have any plans to make default dynamic fallback fonts from the system fonts from the fonts returned from Font.GetOSInstalledFontNames? I know it's not currently possible because we can't get the font file paths from that call, but was wondering if you could just have those be the default fallback internally somehow?

    Thanks!
     
  8. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Short answer Yes.

    However, it will be implemented using the following new function.

    Code (csharp):
    1.  
    2. // Get the file path of all OS fonts.
    3. string[] fontPaths = Font.GetPathsToOSFonts();
    4.  
    5. // Create new Font using one of those paths.
    6. Font osFont = new Font(fontPaths[124]);
    7.  
    8. // Create new font asset using this OS font.
    9. TMP_FontAsset fontAsset = TMP_FontAsset.CreateFontAsset(osFont);
    10.  
    11.  
     
    1g0rrr likes this.
  9. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,167
    Would you please introduce a new method `string FilterMissingCharacters(string s)` to the Font class? So we could check that a font we can load contain glyphs and emojis we want before we try to create font asset

    We then could compare the length of original string and returned string to know how many have been found

    I imaging this method would take any string we need, then remove all character that already contains in that font, and just return missing character as a new string

    Or maybe better if we could have `static string Font.FilterMissingCharacters(string fontName,string s)` to have unity internally check for the font without creating the font asset just yet

    Also, I wish that for simplicity, the TMP_FontAsset should contains `FilterMissingCharacters` in addition to HasCharacters. Is it possible?

    Because I wish I could implement this logic
    Code (CSharp):
    1.  
    2. var tmpText =  TMP_Settings.defaultFontAsset.FilterMissingCharacters(textToSearch);
    3. if(tmpText?.Length < 1)
    4.     return;
    5.  
    6. foreach(var osFontPath = Font.GetPathsToOSFonts())
    7. {
    8.     string tmp = Font.FilterMissingCharacters(osFontPath,tmpText);
    9.     if(tmp?.Length == tmpText?.Length)
    10.         continue;
    11.  
    12.     TMP_Settings.fallbackFontAssets.Add(TMP_FontAsset.CreateFontAsset(new Font(osFontPath)));
    13.     if(tmp.Length < 1)
    14.         return;
    15.  
    16.     tmpText = tmp;
    17. }
    18.  
    And maybe a more complicate logic, such as finding the font that contains most glyphs and load that font first, or filter all fonts that contains wanted glyph but then check the names of font to see that any are bold character and load the bold one first, etc, etc

    Is it possible?
     
  10. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,167
    Also another feature I wish we could have on Text mesh pro is, a fallback font as ttf, not sdf

    I mean I wish that one TMP_Font atlas could contains glyph from many font as a fallback and load them dynamically into the same atlas, instead of creating separate sdf for each font that most likely reuse the same setting anyway

    This feature would be better to handle multi language font system, which most likely came as separate ttf
     
  11. Tommy1977

    Tommy1977

    Joined:
    Mar 24, 2020
    Posts:
    21
    I have same problem This is the code I use:
    I want write in chinsese caracter

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using System.Collections;
    4. using UnityEngine.UIElements;
    5. using TMPro;
    6. using System.Text;
    7. using System.Collections.Generic;
    8. using UnityEngine.UI;
    9. using UnityEngine.SceneManagement;
    10. using System.IO;
    11.  
    12. public class MyClass : MonoBehaviour
    13. {
    14. public TMP_Text vartitle;
    15. string assetPath = "KomikaDemo";
    16. void Start()
    17.     {
    18. vartitle.font = Resources.Load<TMP_FontAsset>(assetPath);
    19. //example chinese caracter
    20. vartitle.text = "Chinese caracter";
    21.  
    22. }
    23.  
    24. void Awake()
    25.     {
    26.         vartitle = vartitle.GetComponent<TMP_Text>();
    27. }
    28. }
    I have try too this
    assetPath = "C:/game/assets/fonts/KomikaDemo.asset";
    assetPath = "C:/game/assets/fonts/KomikaDemo.ttf";
    I have found the error with the path but too when I write all path complete it not work right
    it write Handles ■■■

    Any can help me?
     
  12. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    When using the Resources.Load function, the resource must be contained in a "Resources" folder.

    When referencing TMP resources, they must be placed in the folder specified in the TMP Settings as seen below.

    upload_2021-5-5_13-26-13.png

    In the case of Font Assets, these are expected to be contained in "Resources/Fonts & Materials". I recommend you place your TMP resources in a separate Resources folder from the one found in "TextMeshPro/Resources/...".