Search Unity

TextMesh Pro Overflow adding space to fit in the maximum width

Discussion in 'UGUI & TextMesh Pro' started by Nakoteo, Jul 26, 2019.

  1. Nakoteo

    Nakoteo

    Joined:
    May 21, 2018
    Posts:
    4
    Alright, so basically what I have is a GameObject which contains a TextMesh Pro object. The parent is supposed to adjust itself to the child's width with a Content Size Fitter, which works fine while the text is on a single line. The thing is, once the Overflow kicks in and a second line is made, the parent takes up the maximum width it can take, regardless of the children's size, so I'm stuck with a huge empty space, visible because the parents background is supposed to be scaled to the text. I'm a bit confused, because when I simply skip a line by pressing enter in the Text Input Box, the parent scales properly on two lines. It seems the problem lies with the overflow. I was wondering why the overflow setting was causing this and is there's a way to disable it or change it and to fit the behaviour of a manually entered return.
     
    Vivien_Lynn likes this.
  2. Nakoteo

    Nakoteo

    Joined:
    May 21, 2018
    Posts:
    4
    After looking at it again, it seems that the Text Mesh Pro container doesn't scale to text which contains more than a line, and since my parent container is set so scale based on the children's content, it's taking the maximum size just like the text. How could I make the Text Mesh Pro content box take the width of the text? I've tried playing around with the line info and any other information I could fetch but I haven't been able to do anything. If it's simply by design, i'd like to know though so I can stop toying around with something that won't lead to anything ( ;__; )
     
  3. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Not sure I understand clearly the issue. Can you provide some example screenshots of the behavior you are seeing vs. what you would expect / want?
     
  4. Nakoteo

    Nakoteo

    Joined:
    May 21, 2018
    Posts:
    4
    Yes, sorry, I don't have a picture of the project, but here is an example. The box on the bottom should scale it's width to fit along with the margin I set, but it simply goes to it's maximum possible width, although when there is just one line it works fine.
     

    Attached Files:

  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Again just looking to understand ... Why should the line scale to "Here"?

    The Content Size Fitter uses Preferred Width.

    The Preferred Width is: The width of the (longest) line without wrapping. Ie. From first character of line to linefeed.

    So if you have text that contains something like this.

    A line of text\n
    Another line of text\n
    A last line of text that is longer\n

    In the above example, the preferred width will be the width of the last line.
     
  6. Nakoteo

    Nakoteo

    Joined:
    May 21, 2018
    Posts:
    4
    Ok I did another example which will hopefully clear up what I'm trying to explain. The border around the text is what the border of the text mesh ends up being, so the parent, which contains the text, follows that text border's size and it's background then looks odd because it's too large. The top three boxes are the current behaviour seen.
     

    Attached Files:

  7. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The problem here is the Content Size Fitter is designed to work with Preferred Width and Height which by design ignores word wrapping. Like I said before, Preferred Width is the width that would enable us to avoid breaking the line.

    I think your best option is as follows:

    Set the size of the RectTransform of the text object to match the size of your Area that limits the text.

    Then using a simple script, get the TMP_Text.textBounds which defines the area of the text as seen in the image below.

    upload_2019-8-1_13-25-1.png

    Then add some appropriate padding to the returned text bounds to adjust the size of your background image / frame.

    Note: TMP_Text.textBounds require the text object has already been processed / rendered. So if you are trying to do this in Awake (for instance), you will need to set the text and then use ForceMeshUpdate() to force the text object to be processed right away in order to get valid bounds.

    There should be several posts about ForceMeshUpdate as well as getting the TMP_Text.bounds and TMP_Text.textBounds. The bounds is the bound of the geometry whereas the textBounds are those of the text metrics.

    In the TMP Examples & Extras is a script called TMP_TextInfoDebugTool.cs. If you add this script on a text object, it will allow you to visualize the information contained in the textInfo including the bounds and textBounds.
     
    Rayeloy and EirikWahl like this.
  8. Vivien_Lynn

    Vivien_Lynn

    Joined:
    May 17, 2019
    Posts:
    19
    You can center your left-aligned text without Layout-Groups.

    For a simple Setup create a Canvas.
    1. Add a new Image-Object. 500 wide, 100 heigh, Color = Black. Name it DialogueBox.
    2. Add a new GameObject as a child of the DialogueBox. 480 wide, 80 heigh. Name it TextBounds.
    3. Add a new TMP-Object as a child of the TextBounds. From the Anchor-Presets choose Stretch-Stretch while holding Shift+Alt (or manually set Anchor Min = 0, 0; Max = 1, 1; Pivot = 0.5, 0.5). Name it DialogueText.
    4. Create the following script and add it to your DialogueText.
    Code (CSharp):
    1.     public TMP_Text tmpText; // Assign DialogueText in the Inspector
    2.     private void AssignString(string s)
    3.     {
    4.         // Assign Text to TextObject
    5.         tmpText.text = s;
    6.  
    7.         // Updates the Text-Mesh
    8.         tmpText.ForceMeshUpdate();
    9.  
    10.         // Get TextBounds and use TextBounds to position the Text-Parent
    11.         Bounds bounds = tmpText.textBounds;
    12.         Vector2 newPos = new Vector2(-bounds.center.x, -bounds.center.y);
    13.  
    14.         RectTransform rt = tmpText.transform.parent.GetComponent<RectTransform>();
    15.         rt.localPosition = newPos;
    16.     }
    Use this function to assign your string to the DialogueText-Object.
    Your text should now be centered within the black rectangle.

    Text-Position without the script
    upload_2021-1-16_18-9-59.png

    Text-Position with the script
    upload_2021-1-16_18-10-51.png


    The longest line of text always has as much room on left side as it has on the right side.
     
    Last edited: Feb 8, 2021
    Olipool and leobilck like this.