Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

TextMesh Pro Adjusting size of outline property of TextMeshProUGUI generates garbage all the time.

Discussion in 'UGUI & TextMesh Pro' started by Brother_77, Aug 23, 2022.

  1. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    148
    Hi,

    this is the code I use, and can't seem to figure out a way to avoid GC, and would like to know if it even is possible or GC is just something that comes with altering outline.

    (Also "Glow" is enabled)

    Code (CSharp):
    1.     public float desiredOutline;
    2.     public float fadeTime;
    3.     private float currentOutline = 0;
    4.     private TextMeshProUGUI objectTMP;
    5.     private float baseDesiredOutline;
    6.  
    7.     private void Awake()
    8.     {
    9.         baseDesiredOutline = desiredOutline;
    10.         objectTMP = gameObject.GetComponent<TextMeshProUGUI>();
    11.     }
    12.  
    13.     void Update()
    14.     {
    15.         if (currentOutline == desiredOutline)
    16.         {
    17.             desiredOutline = baseDesiredOutline - currentOutline;
    18.         }
    19.         currentOutline = Mathf.MoveTowards(currentOutline, desiredOutline, fadeTime * Time.deltaTime);
    20.         objectTMP.outlineWidth = currentOutline;
    21.     }

    update.png
     
    Last edited: Aug 23, 2022
  2. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,588
    Check out the following post and thread which should give you more insight on all of this.

    Let me know if you need more information on this.
     
    Brother_77 likes this.
  3. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    148
    I adjusted the script and it creates no GC. Thank you!

    Could you please verify if the adjustments made are good. I mean it works but...

    Code (CSharp):
    1.  public float desiredOutline;
    2.     public float fadeTime;
    3.     private float currentOutline = 0;
    4.     private TextMeshProUGUI objectTMP;
    5.     private Material tmpMaterial;
    6.     private float baseDesiredOutline;
    7.  
    8.     private void Awake()
    9.     {
    10.         baseDesiredOutline = desiredOutline;
    11.         objectTMP = gameObject.GetComponent<TextMeshProUGUI>();
    12.         tmpMaterial = objectTMP.fontMaterial;
    13.     }
    14.  
    15.     void Update()
    16.     {
    17.         if (currentOutline == desiredOutline)
    18.         {
    19.             objectTMP.UpdateMeshPadding();
    20.             desiredOutline = baseDesiredOutline - currentOutline;
    21.         }
    22.         currentOutline = Mathf.MoveTowards(currentOutline, desiredOutline, fadeTime * Time.deltaTime);
    23.         tmpMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, currentOutline);
    24.         // objectTMP.outlineWidth = currentOutline;
    25.     }
    update two.png
     
  4. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    148
  5. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,588
    Modifying the material property directly on the instanced material is definitely the correct approach.

    Are you modifying the outline width on a single text object or doing so on multiple text objects?

    If multiple text objects, is this being updated independently on each text object? If you are modifying multiple text objects all at the same time, I would try to use a common material instance as opposed to creating a new material instance per text object.

    Without having a better understanding of your needs it is hard to provide more insight but again modifying the material property directly is the better route.
     
    Brother_77 likes this.
  6. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    148
    Multiple, but each with different outline parameters ? each has this script attached.

    "Modifying the material property directly on the instanced material is definitely the correct approach."

    So the structure of the code is good? when desired outline is reached (max or min), I update objectTMP.UpdateMeshPadding(); and on each Update() tick adjust the outline via instance of the material with tmpMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, currentOutline);
     
  7. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,588
    That should be fine.

    The mesh padding needs to be updated when the outline grows in size to make sure it remains visible. So in theory, you should not have to keep updating it once you have reached the max size for example. I would suggest experimenting with this on your end.
     
    Brother_77 likes this.
  8. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    148
    So update the mesh padding only once when the max size is reached ?

    And it does not need to be updated on every increase that leads up to max size, only when it is reached right ?
     
  9. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,588
    It should be updated on every increase leading to the max. Alternatively, you could enable Extra Mesh Padding in the Extra Settings of the text object. Depending on the Sampling Point Size to Padding ratio, this could give you enable padding range but you will need to test that.

    Note: We are just talking potential added optimization here.
     
  10. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    148
    Thank you!

    This should be good then

    Code (CSharp):
    1.     public float desiredOutline;
    2.     public float fadeTime;
    3.     private float currentOutline = 0;
    4.     private TextMeshProUGUI objectTMP;
    5.     private Material tmpMaterial;
    6.     private float baseDesiredOutline;
    7.     private bool hasReachedMax = false;
    8.    
    9.  
    10.     private void Awake()
    11.     {
    12.         baseDesiredOutline = desiredOutline;
    13.         objectTMP = gameObject.GetComponent<TextMeshProUGUI>();
    14.         tmpMaterial = objectTMP.fontMaterial;
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         if (hasReachedMax == false)
    20.         {
    21.             objectTMP.UpdateMeshPadding(); // Update padding until max
    22.         }
    23.  
    24.         if (currentOutline == desiredOutline)
    25.         {
    26.             if(hasReachedMax == false) // When max update one last time
    27.             {
    28.                 objectTMP.UpdateMeshPadding();
    29.                 hasReachedMax = true;
    30.             }
    31.  
    32.             desiredOutline = baseDesiredOutline - currentOutline; // Fade the outline opposite direction
    33.         }
    34.  
    35.         currentOutline = Mathf.MoveTowards(currentOutline, desiredOutline, fadeTime * Time.deltaTime);
    36.         tmpMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, currentOutline); // Use material instance to avoid GC
    37.     }