Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

TextMesh Pro Change character material through scripting

Discussion in 'UGUI & TextMesh Pro' started by amigueloferreiracvedia, Feb 3, 2018.

  1. amigueloferreiracvedia

    amigueloferreiracvedia

    Joined:
    Oct 3, 2017
    Posts:
    3
    Hi,

    I would like to create a procedural TextMeshPro material and apply it to a single character of a TextMeshPro component. Is there any way to achieve this? The <material> tag doesn´t fulfill my needs since the material is created at runtime and I´d also like to avoid changing the underlying string.

    Best,
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The material used by any given character is based on the font asset assigned to the text object or to the given character or portions of the text using the <font="Font Asset Name"> tag which would use the Default Material of that font asset or <font="Font Asset Name" material="Material Preset created for this font asset"> or <material="Material Preset for the current font asset">.

    When a text object uses just one font asset, the underlying geometry of this text object points to a single material which references the font atlas texture of this font.

    If a text object uses multiple font assets and / or material presets then for each font asset used (font atlas texture) and unique material (material preset) you end up with an additional mesh / sub text objects for each of those. Again, each material referenced needs to point to a font atlas texture which results a mesh for this material.

    For each material, you end up with a draw call. So if several text objects end up referencing 10 different materials then these text objects would result in 10 draw calls. Depending on whether you are using the normal <TextMeshPro> component or the <TextMeshProUGUI> component batching is handled differently in Unity.

    So can you have a unique material per character? Yes. However, you would have to use either the <font> tag or <material> tag (assuming you were using the same font asset for each of those characters). These materials can be created at runtime. They would have to reference the correct font atlas texture. For each material used, you would end up with a draw call.

    Changing material per character is not going to be efficient and depending on what you actually want to achieve, there might be alternative ways and more efficient ways to get the result you seek. To provide additional insight / suggestions, I would need a better understanding of what you are trying to achieve.
     
  3. amigueloferreiracvedia

    amigueloferreiracvedia

    Joined:
    Oct 3, 2017
    Posts:
    3
    Hi Stephan,

    Thank you for the incredibly detailed answer. I want to focus some characters when hovering the mouse over them by the use of the outline feature. Since I want this to be as generic as possible, I would like to pick up the font asset/material currently used by the text, clone it, activate the outline by enabling the correct shader keyword and setting the outline thickness property.

    I understand the efficiency concerns, but I´d manage the material instantation/pooling myself. So, from what I understood, the only way to change a character material is through the <material> tag right? Even so, how can I use it with procedural materials created at runtime?

    Thank you
     
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    When dealing with materials and for efficiency reasons, I would use a Material Preset (See the following video) which is created ahead of time and used for all the characters that are to be highlighted / interacted with. This way, you would only use two materials which are the main font asset default material used for the normal text and the pre-defined material preset with the outline and other material properties set as you desire.

    Of course you could create a new instance of a material and set the outline but why do that procedurally when you can create this material ahead of time and use it for all highlighted portions of the text. If you absolutely need to create the material at runtime, just make sure you re-use the same instance for the highlighted text to avoid getting 1 draw call per material instance.

    In terms of how to apply this material preset to some characters, you could use the material tag which means updating / inserting the tag in the string. You will need to track what characters are supposed to be using this alternative material and then insert the <material="Alternative Material">Highlighted text</material>.

    If you take a look at example 12a included with TextMesh Pro, you will see how you can track interactions with any given portions of the text. Once you know which character a user is hovering over, you can check what the index of the character is in the source string and then insert the tag where needed. Like I said, you will have to track runs of selected characters to avoid inserting tags for each character.

    P.S. Also take a look at Example 12 and make sure you use the Right Shift Key to hover over some of the characters. This is some alternative way to highlight portions of the text.
     
  5. better_walk_away

    better_walk_away

    Joined:
    Jul 12, 2016
    Posts:
    291
    If we can change the font and material preset of a TextMeshProUGUI via tags, does that means that all fonts and material presets in project will be loaded into memory in the beginning of the game and ready to use at any time?
     
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    What referencing a font asset or material preset in a rich text tag, the font asset and / or material are loaded at that time where they are expected to have been placed in the folder location defined in the TMP Settings.