StacksOnDeck
StacksOnDeck

Reputation: 11

All TextMeshPro Font sizes revert back at Unity runtime after changing with ExecuteInEditMode in the Editor

My Unity scene has multiple objects containing a TextMeshPro component which I want to programmatically change in the Editor using the code below. The script runs successfully when i attach it to an object in the scene, though each of these changed font sizes revert back (to the value before the script executed) after starting the scene in Play Mode.

Initial font size = 0.06 -> attach script to an object, automatically runs OnValidate -> new font size = 0.04 -> Remove script from object, font size remains 0.04 -> Start Play Mode -> font size reverts to 0.06 -> Exit Play Mode -> font size = 0.06

Manually changing the font sizes maintains the new values even during the Play Mode (so no reversion). What could cause the font size persistence issue when utilizing the script?

[ExecuteInEditMode]
public class ChangeAllFonts : MonoBehaviour
{
    void OnValidate()
    {
        TextMeshPro[] textMeshPro_Objects = Object.FindObjectsOfType<TextMeshPro>();
        foreach (TextMeshPro textMeshPro_Object in textMeshPro_Objects)
        {
            textMeshPro_Object.fontSize = 0.04f;
        }
    }
}

Upvotes: 0

Views: 1216

Answers (2)

mijkolsmith
mijkolsmith

Reputation: 53

You could try saving and loading the fontSize value in the playerPrefs or using JSON.

I also recommend not executing the FindObjectsOfType() each time, it is performance-heavy. You do need to use Lists to dynamically assign objects though.


using System.Collections.Generic;

[ExecuteInEditMode]
public class ChangeAllFonts : MonoBehaviour
{
    List<TextMeshPro> textMeshPro_Objects;

    void OnValidate()
    {
        if (textMeshPro_Objects.Count == 0) textMeshPro_Objects = Object.FindObjectsOfType<TextMeshPro>().ToList();
        foreach (TextMeshPro textMeshPro_Object in textMeshPro_Objects)
        {
            PlayerPrefs.SetFloat("FontSize", 0.04f);
        }
        PlayerPrefs.Save();
    }
}

Then in your game code you need to do the same as well:

public class MyClass : MonoBehaviour
{
    List<TextMeshPro> textMeshPro_Objects;

    void Start()
    {
        if (textMeshPro_Objects.Count == 0) textMeshPro_Objects = Object.FindObjectsOfType<TextMeshPro>().ToList();
        foreach (TextMeshPro textMeshPro_Object in textMeshPro_Objects)
        {
            textMeshPro_Object.fontSize = PlayerPrefs.GetFloat("FontSize");
        }
    }
}

Upvotes: 0

Adam B
Adam B

Reputation: 3861

Not sure but I suspect the issue has to do with serialization. You’re changing the value, but not the serialized value that unity stores and that persists between sessions. So when you hit play the editor session ends, and Unity searches for the serialized value.

I would suggest accessing the font property from a serialized object and changing it that way. So you’ll need to convert the TMP objects to serialized objects, find the correct property, and then modify it.

Having this script run for all TMP objects every time OnValidate gets called is likely going to be performance intensive. Might be better to make it a button or menu item to only run when you decide to run it.

Upvotes: 1

Related Questions