Search Unity

Localization, font switching and font material presets

Discussion in 'UGUI & TextMesh Pro' started by PandaArcade, Jan 2, 2020.

  1. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    130
    In our game, we have one primary static font that we use for English with several material presets. This font has several fallback dynamic fonts to cover the occasional appearance of other languages. I've noticed that I don't have to set up material presets for the fallback fonts used in this setup, TMP seems to generate an instance of the primary fonts material automatically.

    I've got several fonts set up for different languages each with the appropriate fallbacks setup as explained above.

    My problem - I'm not sure how to handle material presets when switching fonts due to a language change. I could create copies of my English font material presets and switch them out at the same time I switch my font, but then I have to maintain ~210 material presets (or create tools to maintain them).

    I was thinking I'd lazily create an instance of a material preset when required and cache it for quick lookup.

    How would you handle this? Can you please give some suggestions :)

    It would be neat if when setting the font of a Text component via script if I would set a flag to maintain material properties automatically and under the hood, it would do what I think it does for fallback fonts :rolleyes::)
     
    Last edited: Jan 5, 2020
  2. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    130
    @Stephan_B if I go ahead and create duplicate material presets for each language's primary static font what is the correct and most efficient way to set the text components font and material preset? Do I need to call UpdateFontAsset after setting the font? I found a bunch of posts about this but they are all quite old.

    Code (CSharp):
    1. TextComponent.font = tmpFont;
    2. TextComponent.fontMaterial = fontMaterial;
    3. TextComponent.text = localizedString;
     
  3. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Since fonts can vary greatly in design, it is almost unavoidable that you will need to create material presets for each of the fonts.

    It is possible for example that Outline thickness of value X will work fine with a different font but most of the time, designers end up tweaking those material property values to get the visual they want. It all depends on how similar the fonts you have selected are for those different languages.

    Although having to manage several Primary font assets with fallbacks and related material presets per language adds complexity on the resource management side, it guarantees the visual results for any of those languages. Materials are pretty small in terms of size so having more material presets doesn't really impact build size.

    Since localization often involves more than just changing font assets like changing other resources such as textures, sounds, sprites, colors, etc. Having some type of tool to manage these resources for any given language is usually the best way to go.

    Back to the topic... again assuming the fonts you have selected are very similar in design / weight, you could create the required materials at runtime but that also adds complexity.

    Personally, I would lean towards having material presets for each of those primary font assets / fallback for each of the languages supported.

    To manage the swapping of resources when the language change. Like I said before you could use a tool like I2 Localization which should be able to handle all of this.

    You could also implement your own tool to track all the resources that need to change when the language is switched. Your tool would need to be sure to assign the proper font asset to your text objects, assign the correct material preset (if needed), localized strings and perhaps change other properties like point size, etc.

    A recently added feature that could be helpful in this process is the new Text Style which allows you to assign a style to an entire text object. Since TMP now support Global StyleSheets (defined in the TMP Settings) and Local StyleSheets which can be assigned to the individual text object, the visual treatment of the text object could be controlled this way.

    For instance, you could create a StyleSheet for English where you would define Styles for Headers, Body, etc. These styles could specify the font that is to be used like <font="My English Font Asset" material="The material preset to use">. So to handle switching to Chinese, you would simply replace the StyleSheet by the Chinese one and all the text using a Text Style like Header, Body would change automatically. You would still need to change the text itself but that should be it. This is just a suggestion but that could be a new way / simpler way to handle this.

    This is a lot of stuff to think about. Let me know your thoughts.
     
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Additional Notes:

    For testing purposes, I created a Dynamic Font Asset using NotoSans-Regular to which I added a few characters and then switched the font asset to be static. I created a dynamic fallback for it which I then assigned as fallback to the static NotoSans-Regular SDF. I also created a material preset with an outline for this primary static font asset.

    I repeated the process using the NotoSansCJK-Regular font.

    I created a StyleSheet for English that contains the following definition for the Header style where a specific the NotoSans-Regular is referenced and a color.

    upload_2020-1-14_14-56-5.png

    I created another StyleSheet for CJK which also contains a Header style but referencing the NotoSansCJK-Regular.

    upload_2020-1-14_14-57-32.png

    I created a text object which by default was assigned the LiberationSans SDF font asset.

    I assigned the English StyleSheet to the text object in the Extra Settings and selected the Header style in the Text Style option in the text inspector panel. This resulted in the text switching to NotoSans-Regular SDF and the appropriate Material Preset.

    Both Primary static font assets only included "ABC" as characters. Adding "D" to the text correctly added the D to the dynamic appropriate fallback and material preset.

    upload_2020-1-14_15-17-0.png

    As you can see above, the ABC are using the NotoSans-Regular SDF with the material preset referenced in the <font> tag in the Header style. The D is using the fallback with an instance material preset derived from the primary.

    Changing the StyleSheet of the text object from English to CJK works as expected and correctly switches to the correct font asset, fallback and material preset.

    Interestingly enough, in this test I used NotoSans-Regular and NotoSansCJK-Regular and although these two fonts are named NotoSans, their metrics are not the same thus resulting in differences in alignment. Fortunately, we can edit these metrics in the Font Asset Inspector to normalize / adjust their alignment to make sure these sort of blend better with each other.
     
  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Previously posted information about the Text Style feature:

    Text Styles
    Text Styles allow the application of a style to a text object. This is very useful when a specific style applies to the whole object which previously required using the <style> tag at the start and end of the body of the text which was not ideal in some cases and also error prone.



    The Text Style pull down shows the Text Styles available. Text Styles are defined Globally in the TMP Settings Default StyleSheet and can now also be Local by assigning a StyleSheet in the Extra Settings of the text object. If a style is defined in the local and global StyleSheets, the local style will override the global style.

    It is possible to use a Text Style and styles in the body of the text. Nesting of styles has also been improved.
     
  6. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    130
    Thank you so much for the detailed explanation @Stephan_B :D

    I'm using Unity 2019.2.17f1 and TMP 2.0.1 and I see Default Style Sheet asset in my project and I can assign TextComponent.fontStyle in code but I don't see any reference to Text Style in the inspector. I checked in the package manager and I don't see a newer version of TMP.

    Unity_7xGgjNjWGM.png
     
  7. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    You need the latest which is version 2.1.0-preview.3. Preview 4 should be out soon.
     
  8. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    130
    I have 2.1.0-preview.1 which is the latest I can see in the package manager :(
     
  9. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Preview 3 is available. It should be visible in the Package Manager.

    Make sure you have in the Advanced Settings of Package Manager show preview packages.
     
  10. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    130
    Sorry, I mistakenly said I had the 2.1.0-preview.1 installed. I only have 2.0.1 installed. Can I not see 2.1.0 because we're using Unity 2019.2.18f1?

    I do have Show preview packages enabled.

    Packages.jpg
     
  11. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    It should be available for 2019.x including 2019.2.x. Not sure why it is not visible in this case.

    I would suggest creating a new / empty project to see if the behavior is consistent and if version 2.1.0-preview.3 shows up.
     
  12. PandaArcade

    PandaArcade

    Joined:
    Jan 2, 2017
    Posts:
    130
    I created a new project and yes it was visible in the Package Manager. I discovered we had added
    "registry": "https://staging-packages.unity.com"
    to our manifest.json file because we need access to a package in staging. We thought it would additionally show us the packages in staging but it evidently was exclusively showing us packages in staging.

    Thanks for your help :D
     
    Stephan_B likes this.