Search code examples
c#unity-game-engineuitextfieldfont-scaling

How do I scale individual TextMesh Pro Text Objects in a Vertical Layout Group evenly?


Unity Version: 5.6.5f1 Personal

TextMesh Pro Version: 1.0.56.0b3

I am attempting to create dynamic TextMesh Pro text blocks that are stored in a Vertical Layout Group UI Element. Each block of text is stored in its own gameobject, and all gameobjects are children of the Vertical Layout Group. All TextMesh Pro objects use the same font and have the "Auto-Sizing" flag enabled, so that they scale within the bounds of the Vertical Layout Group. Ideally, all text blocks should have the same font-size when scaling. See the current Vertical Layout Group Inspector with hierarchy for the Group and Child TextMesh Pro Text Blocks.

Vertical Layout Group Inspector

The problem is that if one block of text consists of two lines, and another block consists of three lines, both blocks will take up roughly half of the Vertical Layout Group. However, the first block's font-size will be around 2/3 of the second block's font-size. In practice, I will also occasionally see the two-line text block span three lines with a much larger font-size. See the image link below for details.

Output In Practice vs. Desired Outcome

The goal here is not to modify the Vertical Layout Group in any way. The contents must fit within the group's fixed-position and fixed-size. The blocks of text must be separate objects for the purposes of defining clickable regions. Each region spans over the entire text block, and will resize as the text changes.

Clickable Region Overlay Demonstration

The code behind the Monobehaviour that manages the Vertical Layout Group maintains an array of strings which contain the aforementioned text of all text blocks. Changes, such as additions, edits, and removals to this array appear as changes to the Vertical Layout Group by extension. I'm pretty certain at this point that I'll need to implement functionality to manipulate the text boxes whenever a change occurs, rather than rely on auto-sizing from TextMesh Pro, but it is at this point, that I'm stuck.

How can I achieve the desired outcome, programmatically or otherwise, of maintaining a font-size that is the same across all text boxes added to the Vertical Layout Group while distributing the space of the group amongst text boxes of varying content such that I utilize as much of the Vertical Layout Group as possible?

EDIT: Added Vertical Layout Group Inspector and Object Hierarchy as an image to this question.


Solution

  • As Ian H. stated, Auto-Size scales the font-size to fit the content of the text into the object's rectangle. While the individual TextMesh Pro blocks must be distinct objects, the Vertical Layout Group was deemed as part of an object with "fixed-position and fixed-size." The solution to this problem is derived from using Auto-Sizing in a TextMesh Pro text block that is the same size as the Vertical Layout Group to determine the font-size of all child objects, then using that font-size for each child knowing that the fit is assured. First, let's begin with a proposed hierarchy:

    Hierarchy with Raw Text and Vertical Layout Group

    A new gameobject with a single TextMesh Pro text block using the same RectTransform values as the Vertical Layout Group is used to simulate how the text should be scaled relative to the area it's contained in. As outlined in the question, several paragraph entries were stored into an array that maintains them. Each string element was output to the Raw Text block, separated by System.Environment.Newline characters.

    Raw Text Inspector

    Raw Text Viewed In Scene

    Note the use of Auto-Size. The issue mentioned in the question is that the text scales improperly when broken into several distinct objects. However, as a single object, Auto-Size will work as intended, providing the target font-size needed for each individual object. Now, a method can Instantiate TextMesh Pro text block objects and store them into the Vertical Layout Group. The difference in this case is that each object is deliberately set to the font-size determined beforehand.

    Instantiated Text Inspector

    For visualization purposes, each Instantiated Text object consists of the TextMesh Pro text block, as well as a color box added as a child object that encompasses the bounds of the text block. This will still function as intended without the color box. A comparison between the results of the Raw Text overlaying the Instantiated Text is shown in the image below, where the Raw Text is red and the Instantiated Text is black.

    Comparison: Raw vs. Instantiated Text

    The text itself will not overlap perfectly at every point. This is due to the fact that the centering of the Raw Text block produces a different effect from the centering of multiple Instantiated Text blocks, each having their own center. However, for the purposes of a list of clickable regions defined by text, this behavior is closer to the end goal than what the Raw Text output provides. Removing the Raw Text from visibility, this is the final result.

    Result: Instantiated Text Viewed in Scene

    Further testing shows that this behavior can be duplicated with text of arbitrary amounts. Furthermore, the user can impose font-size restrictions for the Instantiated Text Blocks by defining a minimum and maximum font size in the Raw Text Auto-Size Properties. Below, you can see the changes in font-size as some elements are removed, as well as an imposed maximum font-size when the amount of text is reduced to two entries.

    Four Entries - Increased Font Size / Maximum Font Size Not Reached

    Two Entries - Maximum Font Size Reached / Padding Increased