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

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)

    public float desiredOutline;
    public float fadeTime;
    private float currentOutline = 0;
    private TextMeshProUGUI objectTMP;
    private float baseDesiredOutline;

    private void Awake()
    {
        baseDesiredOutline = desiredOutline;
        objectTMP = gameObject.GetComponent<TextMeshProUGUI>();
    }

    void Update()
    {
        if (currentOutline == desiredOutline)
        {
            desiredOutline = baseDesiredOutline - currentOutline;
        }
        currentOutline = Mathf.MoveTowards(currentOutline, desiredOutline, fadeTime * Time.deltaTime);
        objectTMP.outlineWidth = currentOutline;
    }

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.

1 Like

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…

 public float desiredOutline;
    public float fadeTime;
    private float currentOutline = 0;
    private TextMeshProUGUI objectTMP;
    private Material tmpMaterial;
    private float baseDesiredOutline;

    private void Awake()
    {
        baseDesiredOutline = desiredOutline;
        objectTMP = gameObject.GetComponent<TextMeshProUGUI>();
        tmpMaterial = objectTMP.fontMaterial;
    }

    void Update()
    {
        if (currentOutline == desiredOutline)
        {
            objectTMP.UpdateMeshPadding();
            desiredOutline = baseDesiredOutline - currentOutline;
        }
        currentOutline = Mathf.MoveTowards(currentOutline, desiredOutline, fadeTime * Time.deltaTime);
        tmpMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, currentOutline);
        // objectTMP.outlineWidth = currentOutline;
    }

?

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.

1 Like

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);

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.

1 Like

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 ?

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.

Thank you!

This should be good then

    public float desiredOutline;
    public float fadeTime;
    private float currentOutline = 0;
    private TextMeshProUGUI objectTMP;
    private Material tmpMaterial;
    private float baseDesiredOutline;
    private bool hasReachedMax = false;
   

    private void Awake()
    {
        baseDesiredOutline = desiredOutline;
        objectTMP = gameObject.GetComponent<TextMeshProUGUI>();
        tmpMaterial = objectTMP.fontMaterial;
    }

    void Update()
    {
        if (hasReachedMax == false)
        {
            objectTMP.UpdateMeshPadding(); // Update padding until max
        }

        if (currentOutline == desiredOutline)
        {
            if(hasReachedMax == false) // When max update one last time
            {
                objectTMP.UpdateMeshPadding();
                hasReachedMax = true;
            }

            desiredOutline = baseDesiredOutline - currentOutline; // Fade the outline opposite direction
        }

        currentOutline = Mathf.MoveTowards(currentOutline, desiredOutline, fadeTime * Time.deltaTime);
        tmpMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, currentOutline); // Use material instance to avoid GC
    }