Search Unity

TextMesh Pro Force TextMeshPro to reload SDF asset

Discussion in 'UGUI & TextMesh Pro' started by robal1991, Feb 14, 2019.

  1. robal1991

    robal1991

    Joined:
    Mar 31, 2016
    Posts:
    33
    Hello, I have an application where before build I need to adjust TMPro SDF asset parameters such as bold weight etc. because I use both gamma and linear color space depending on target platform and I need to adjust how fonts look like.

    Let's take simple example:
    I'm changing bold weight via editor script before build:
    Code (CSharp):
    1. font.boldStyle = 0.75f;
    where font is my TMP_FontAsset type object.

    I see that the value is being changed in the inspector correctly, but somehow I can't see any effect in the scene/game tab in Unity. But if I change the body weight value or any other value of SDF asset in the inspector the body weight change is applied correctly immediately.

    My question is how can I force TMPro to reload/refresh SDF asset. I tried EditorUtility.SetDirty, AssetDatabase.Refresh etc. Nothing worked for me. It seems that I'm missing something very simple.

    I can add that changing SDF material parameters is working as expected:
    Code (CSharp):
    1. font.material.SetFloat("_OutlineSoftness", 0.1f);
    2. font.material.SetFloat("_FaceDilate", -0.05f);
    Thanks for any suggestions.
     
    Last edited: Feb 15, 2019
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Calling UpdateMeshPadding() on the affected text objects should do the trick.
     
  3. robal1991

    robal1991

    Joined:
    Mar 31, 2016
    Posts:
    33
    Ok, but it is a method on TMP_Text object... I have to call this method now on every Text in my project.... Is there any equivalent method for TMP_FontAsset?

    I'm calling now
    Code (CSharp):
    1. AssetDatabase.Refresh();
    2. EditorUtility.SetDirty(font);
    3. AssetDatabase.SaveAssets();
    after my changes and font asset is serialized and saved correctly. Value in inspector is also updated correctly.

    It is wierd though that if I just type another 0 after comma to the bold weight value, for example if I change 1.3 to 1.30 the change is applied correctly immediately as expected. So somehow changing value from inspector is calling something which I'm missing in my build script.
     
    Last edited: Feb 15, 2019
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Some background info to explain what is going on...
    The bold weight is essentially Dilation which can affect the size of the geometry which is why calling UpdateMeshPadding() is necessary on the affected text objects.

    In the Editor (only), there is a callback that occurs when some properties of font assets are modified which ends up propagating to all text objects where if the object is using said font asset then it ends up updating the mesh padding and setting the object dirty so that its geometry is updated.

    Normal and Bold weight are actually properties of the material and as such can be modified on the material.

    To modify those and instead of using something like
    Code (csharp):
    1.  
    2. // Lets avoid using strings to modify material properties.
    3. font.material.SetFloat("_OutlineSoftness", 0.1f);
    4.  
    5. // Instead use the following TMP utility
    6. font.sharedMaterial.SetFloat(ShaderUtilities.ID_WeightBold);
    7.  
    Also keep in mind that using font.material will result in an instance of a material being created whereas using font.sharedMaterial will not and modify this property on all text objects that share this material which is likely what you want. Assuming you didn't want to modify the sharedMaterial because it is an asset or something then do create an instance material but then assign it to all text objects and then modify the single instance instead of ending up with lots of material instance to which you modify the bold weight. If all objects share the same material then you get 1 draw call. If you have 10 instance of the same material then you get 10 draw calls which is less efficient.

    Lastly, increasing the bold weight without updating the mesh padding can result in clipping as the geometry will not grow with the increased weight. Now you could sort of get around this and avoid having to call UpdateMeshPadding on all text objects by setting Extra Padding to true on all text objects.

    Final note: In order to assign the same instanced material to all text objects that are supposed to share this instance, you will need to get a list of those objects. If you have a list of those objects (which you should acquire in Awake or Start but not in Update as you only need to get a reference to these objects once, then you may as well use that list to call the UpdateMeshPadding on all text objects after changing their bold weight.

    Hopefully this information help.
     
    ilmario likes this.
  5. robal1991

    robal1991

    Joined:
    Mar 31, 2016
    Posts:
    33
    I replaced
    Code (CSharp):
    1. font.boldStyle = 0.75f;
    with
    Code (CSharp):
    1. font.material.SetFloat(ShaderUtilities.ID_WeightBold, 0.75f);
    and it's working :) Thanks for help.
     
    Stephan_B likes this.