Search Unity

TextMesh Pro When TMP text created with outline on, can never turn it back off.

Discussion in 'UGUI & TextMesh Pro' started by TeamDefiant, May 29, 2018.

  1. TeamDefiant

    TeamDefiant

    Joined:
    Mar 29, 2017
    Posts:
    50
    I have a program which creates closed captions. If I create a new line of text with the outline turned off, when I use my outline toggle button, they toggle on and off correctly.
    If I create a line of text (in exactly the same way as before) but with outlines turned on, I can never turn them off again.

    Code (CSharp):
    1. public void addNewSubtitle( string lineOfText )
    2. {
    3.     GameObject scrollingGO = Instantiate(scrollingTextPrefabGO, scrollingTextParentGO.transform);
    4.  
    5.     scrollingGO.GetComponent<TextMeshProUGUI>().text = lineOfText;
    6.     scrollingGO.GetComponent<TextMeshProUGUI>().color = sceneManager.selectedColor;
    7.     scrollingGO.GetComponent<TextMeshProUGUI>().outlineWidth = getOutline(false);
    8.  
    9.     scrollingTextGOList.Add(scrollingGO);
    10. }
    11.  
    12.  
    13. public float getOutline(bool hasOutline)
    14. {
    15.     if (hasOutline) return textMeshOutlineValue;
    16.     else return textMeshNoOutlineValue;
    17. }
    18.  
    19.  
    20. void Update()
    21. {
    22.     if(Input.GetKeyDown(KeyCode.Space)) addNewSubtitle( "The app has been running for " + Time.time.ToString() + " seconds." );
    23.  
    24.     if (sceneManager.isSubtitleScrollingText) // true or false
    25.     {
    26.         for (int i = ( scrollingTextGOList.Count -1 ); i >= 0; i--)
    27.         {
    28.             scrollingTextGOList[i].GetComponent<TextMeshProUGUI>().outlineWidth = getOutline(sceneManager.isSubtitleBorderSelected);
    29.         }
    30.     }
    31. }
    32.  
    What the code does is clone an existing TMP object, change the text, then add it to a list of existing subtitles. In the create method, we always set the outline off as the outline is turned of/off in the update method.
    If sceneManager.isSubtitleScrollingText is false when i call addNewSubtitle, everything is fine. If sceneManager.isSubtitleScrollingText is true when i call addNewSubtitle, then I get the problem. I can never turn the subtitles off for that line of text.
     
  2. TeamDefiant

    TeamDefiant

    Joined:
    Mar 29, 2017
    Posts:
    50
    On further examining, the line of text which toggles correctly has its shader as follows:
    Arial_Unicode_SDF Material (instance)
    The incorrect lines of text have the following shader:
    Arial_Unicode_SDF Material (instance) Masking ID: 1, and the properties are greyed out.

    What's this Masking thing, and how can I change/disable it?
     
  3. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The first thing to keep in mind is that using the "outlineWidth" property on a text object results in an instance of a material being created. The creation of an instance material when accessing the material of an object is in keeping with Unity conventions. However, this might not be what you want here especially if you have several text objects.

    Assuming you have several text objects where some are plain text without an outline and other with an outline but with this outline being consistent between all the objects that have an outline, I would use two materials presets for this.

    The first material preset would likely the default material of the font asset and the other a material preset with the outline settings as you need them.

    Depending on the state of the text object, I would simply assign via the TMP_Text.fontSharedMaterial one or the other material preset based on the state of the object.

    This implementation would have the benefit of using just two materials instead of potentially several instances. Since all text objects would share these, this would reduce draw calls as objects that share the same material would potentially batch.

    The only time where it makes sense to use material instances is when you need unique visual / material properties for each text object. When text objects share the same visual treatment / material properties, it is best to create / use material presets and then assign the appropriate preset to the text objects.

    In terms of why you are running into issues with your current implementation, it is likely due to the fact that material instances are used where your code ends up trying to change / disable the outline on the wrong material instances.
     
  4. TeamDefiant

    TeamDefiant

    Joined:
    Mar 29, 2017
    Posts:
    50
    Stupid question, but when I use the example materials which came with TMP, or a new material I created by duplicating a sample material and renaming it, the text is appearing all messed up. (As if the characters where being sampled from the wrong place within the atlas.) Is there anything else I need to do to ensure that the text appears correct? None of the font materials provided by TMP are working, not just the two I created.
    Am I missing a setup file or something which needs to be applied? (The text appears correct until I change the material with the scrollingGO.GetComponent<TextMeshProUGUI>().fontSharedMaterial command.


    At least the outline changes correctly, even though the glyphs are messed up. :)
     
  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    In order for the text to render correctly, the texture (font atlas) referenced by the material must be the same as the font atlas texture of the font asset being used. Any mismatch will result in roughly what your image is showing.

    When creating Material Presets using the Material Context Menu, TMP creates a new material which references the font atlas texture of the font asset currently assigned to the text object. Please see the following video as these concepts are very important to understand.

    So when I described using two material presets (one for plain text and one for outline), this implies these material presets were created from the font asset to which they will be assigned. If you will be using 4 different font assets (created from 4 different source font files like Arial, Impact, Helvetica, etc.), you will have to create material presets for each of these. Again each font asset contains a unique font atlas texture which each of the material presets for those font assets must reference.
     
  6. TeamDefiant

    TeamDefiant

    Joined:
    Mar 29, 2017
    Posts:
    50
    Cheers. I have it sorted now. ;)
     
    Stephan_B likes this.
  7. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Most excellent :)