Search Unity

TextMesh Pro Getting the size of text in Unity scale

Discussion in 'UGUI & TextMesh Pro' started by vrlabntnubackup, Mar 28, 2019.

  1. vrlabntnubackup

    vrlabntnubackup

    Joined:
    Feb 15, 2019
    Posts:
    4
    How would one go about getting the size of the text in Unity scale? I don't see how I would translate font size into Unity scale and I'm not quite sure what is included in the field
    textmeshproObject.textInfo.lineInfo[index].lineHeight
    either. (which I asked about in the Unity Answers section here)


    What I would like to end up with is a way of saying that the an individual character or a line of the text is a certain centimeters high.
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Font Metrics are defined in the font file. These metrics are in Units per EM which is typically 2048.

    Below are the Metrics of LiberationSans

    upload_2019-3-29_1-2-47.png

    LineHeight = Ascender - Descender + lineGap which in this case is 2355.

    In the case of the LiberationSans SDF Font Asset included with TMP. It has a sampling point size of 86. So computing the LineHeight for that sampling point size, we get 2355 / 2048 * 86 = 98.8916.

    When the text is displayed at 1:1 or at 86 point size, the lineHeight or distance from baseline to baseline will be that 98.89 pixels. So depending on your screen DPI, you should be able to compute the size in Centimeters.
     
    vrlabntnubackup likes this.
  3. vrlabntnubackup

    vrlabntnubackup

    Joined:
    Feb 15, 2019
    Posts:
    4
    Thanks for the reply, Stephan!

    Given I am displaying text in a 3D environment, would it be correct to say that at point blank a text using the LiberationSans font at a point size of 86 it would be 98,9*DPI cm tall?

    Also pardon my ignorance, but where do you find that window with the font properties? I assume the window in Unity displays the same properties (see below), but the values are very different?
     
    Last edited: Mar 29, 2019
  4. vrlabntnubackup

    vrlabntnubackup

    Joined:
    Feb 15, 2019
    Posts:
    4
    Somewhat off topic why does it seem like all the values are calculated from the center of the rect transform as well?
    Example where Text is a TextMeshPro object:

    Code (CSharp):
    1.          
    2.             for (int i = 0; i < text.textInfo.lineCount; i++)
    3.             {
    4.                 fh.WriteToFile(string.Format("Line {0} BASELINE {1} ASCENDER {2} DESCENDER {3}",
    5.                     i, text.textInfo.lineInfo[i].baseline, text.textInfo.lineInfo[i].ascender, text.textInfo.lineInfo[i].descender));
    6.             }
    7.  
    This makes a file that looks like this:

    Line 0 BASELINE 0.454742 ASCENDER 0.5 DESCENDER 0.4441497
    Line 1 BASELINE 0.3972384 ASCENDER 0.4424964 DESCENDER 0.3866461
    Line 2 BASELINE 0.3397347 ASCENDER 0.3849927 DESCENDER 0.3291425
    Line 3 BASELINE 0.2822311 ASCENDER 0.3274891 DESCENDER 0.2716388
    Line 4 BASELINE 0.2247275 ASCENDER 0.2699855 DESCENDER 0.2141352
    Line 5 BASELINE 0.1672239 ASCENDER 0.2124819 DESCENDER 0.1566316
    Line 6 BASELINE 0.1097202 ASCENDER 0.1549782 DESCENDER 0.09912795
    Line 7 BASELINE 0.05221659 ASCENDER 0.09747458 DESCENDER 0.04162431
    Line 8 BASELINE -0.005287051 ASCENDER 0.03997093 DESCENDER -0.01587933
    Line 9 BASELINE -0.06279069 ASCENDER -0.01753271 DESCENDER -0.07338297
    Line 10 BASELINE -0.1202943 ASCENDER -0.07503635 DESCENDER -0.1308866
    Line 11 BASELINE -0.177798 ASCENDER -0.13254 DESCENDER -0.1883903
    Line 12 BASELINE -0.2353016 ASCENDER -0.1900436 DESCENDER -0.2458939
    Line 13 BASELINE -0.2928053 ASCENDER -0.2475473 DESCENDER -0.3033975
    Line 14 BASELINE -0.3503089 ASCENDER -0.3050509 DESCENDER -0.3609012
    Line 15 BASELINE -0.4078125 ASCENDER -0.3625546 DESCENDER -0.4184048
    Line 16 BASELINE -0.4653162 ASCENDER -0.4200582 DESCENDER -0.4759085
    Line 17 BASELINE -0.5228198 ASCENDER -0.4775618 DESCENDER -0.5334121
     
    Last edited: Apr 2, 2019
  5. vrlabntnubackup

    vrlabntnubackup

    Joined:
    Feb 15, 2019
    Posts:
    4
    Sorry I'm asking a lot, this information is important for my thesis. Happy to give more context if needed.

    When you were talking about needing DPI/PPI of the display earlier to calculate into cm, that would translate into a physical size on the display right? What I am after though is the lineHeight in terms of Unity units, whether or not that is representative of real-world measures, but I wouldn't that be independent of display PPI?

    [EDIT] I might be overcomplicating things, as my experiment seem to indicate that lineHeight is actually in Unity size, which was my initial impression and is probably obvious. (I simply put a cube behind the text and scaled it to be the same height and width as lineHeight...)
     
    Last edited: Apr 2, 2019
  6. wechat_os_Qy09lXXTy_UHSAp306OFg3cN4

    wechat_os_Qy09lXXTy_UHSAp306OFg3cN4

    Joined:
    Feb 21, 2020
    Posts:
    1
    Could you please tell me the name of this font properties inspecting software? thank you.
     
  7. gameboy

    gameboy

    Joined:
    Mar 25, 2009
    Posts:
    37
    Open the font using FontCreator for windows.
    From the menu, click on the following:
    Font >> Properties... >> Metrics tab
     
  8. VoodooDetective

    VoodooDetective

    Joined:
    Oct 11, 2019
    Posts:
    239
    Could someone post an example of how to calculate line height programmatically?

    This value:
    Code (CSharp):
    1. textComponent.textBounds.size.y
    Isn't set until the end of the frame, but I need the information before the end of the frame. So I'm trying to find a way to calculate it manually:

    Code (CSharp):
    1. visibleLines * lineHeight
    I don't know how to calculate line height and textComponent.font.faceInfo.lineHeight is not what I want it to be. The actual height is:
    52.9, but lineHeight returns 156.4.

    Here's how I'm calculating line count:
    Code (CSharp):
    1.         private int VisibleLineCount()
    2.         {
    3.             int line;
    4.             int characterCount;
    5.             for (line = 0, characterCount = 0; line < textComponent.textInfo.lineInfo.Length; line++)
    6.             {
    7.                 characterCount += textComponent.textInfo.lineInfo[line].characterCount;
    8.                 if (textComponent.maxVisibleCharacters <= characterCount || characterCount >= textComponent.textInfo.characterCount)
    9.                 {
    10.                     break;
    11.                 }
    12.             }
    13.             return line + 1;
    14.         }
     
    Last edited: May 14, 2021
  9. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    When the properties of a text object have been changed, the text object will be processed that frame and just before culling take place which is basically the last step before the camera is rendered.

    As per the above, if you were to change the properties of a text object and then immediately check the content of the textInfo, this content would not be correct as the text object hasn't been processed yet. For most use cases, this is fine but for cases where you need to check how a change will affect the bounds of the text or to query the textInfo, you can call ForceMeshUpdate() on the text object to force it to be processed right away.

    Note that when calling ForceMeshUpdate() all properties that have been changed will be processed and if no further changes are made before culling takes place then this object will skip its normal update.
     
  10. VoodooDetective

    VoodooDetective

    Joined:
    Oct 11, 2019
    Posts:
    239
    Ahh ok great! So a little more context. I'm changing maxVisibleCharacters every frame.

    You're saying, after i'm done changing maxVisibleCharacters, I can safely/efficiently call:
    Code (CSharp):
    1. ForceMeshUpdate()
    and that that will, practically, change the order of when the text bounds update from the culling stage, to right when I make the cull? Is that right? I just want to make sure I'm not doing something grossly inefficient.
     
  11. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    ForceMeshUpdate() simply forces the text object to be updated immediately instead of later in the frame. So provided you don't make any other property changes after that, the text object will not be updated again that frame thus making this as efficient.
     
  12. VoodooDetective

    VoodooDetective

    Joined:
    Oct 11, 2019
    Posts:
    239
    Perfect, thank you!