Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Fonts for International Chat: Finding System Fonts for Run-Time Foreign Glyphs?

Discussion in 'UGUI & TextMesh Pro' started by alex_roboto, Aug 12, 2020.

  1. alex_roboto

    alex_roboto

    Joined:
    Nov 11, 2019
    Posts:
    24
    Our game has an international audience. We will launch in the England with English glyphs and we will launch in Japan with Japanese glyphs. However, Japanese players can play with English players and both English and Japanese players can text chat with each other and view each other's names. It would be nice if Japanese speakers using English app could see the Japanese glyphs and vice versa.

    I can think of some solutions:

    1) We ship English and Japanese Fonts to both English and Japanese clients. However, this bloats the client size and as we ship more and more languages the problem gets worse and worse: Cyrillic, Chinese (simplified), Chinese (Traditional), Korean, etc. I guess this problem could be made less severe by downloading assets bundles with the fonts but it still makes a big install size.

    2) When we encounter a glyph we don't know how to display (HasCharacters()) we try to load a system font that has the glyph and switch to that font. This works... sort of. It works if I know a system font that has the glyph. But I ended up with a complex table of glyph codes -> font names that is different per platform (Windows has different system fonts than iOS than Android.) This approach failed when I tried to mix Japanese and English glyphs in one TextMeshPro text field.

    3) I guess a solution would be to list all system fonts that cover our languages as fallbacks and change this list per operating system (so we'd have one list for iOS, one for Android, and one for WebGL)... however, the way the system is setup, we'd have to ship the fonts. Ideally, these could be system fonts so we wouldn't have to ship them. Is there anyway to list a system font as a fallback?

    Anyone have any suggestions for displaying chat which can be in any language? We don't care if foreign glyphs look mismatched, we just don't want to show the empty square.

    Thanks in advance!
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    You can use the following API to get the path to available OS fonts.

    Code (csharp):
    1.  
    2. // Get paths to OS Fonts
    3. string[] fontPaths = Font.GetPathsToOSFonts();
    4.  
    5. // Create new font object from one of those paths
    6. Font osFont = new Font(fontPaths[index]);
    7.  
    8. // Create new dynamic font asset
    9. TMP_FontAsset fontAsset = TMP_FontAsset.CreateFontAsset(osFont);
    10.  
     
    alex_roboto likes this.
  3. alex_roboto

    alex_roboto

    Joined:
    Nov 11, 2019
    Posts:
    24
    For anyone else trying to do this:
    1. First, I created a list of system font names per platform that support the languages we need. For example, Windows 10 has the system font "simsun.ttc" which covers Chinese characters. Android has "DroidSansFallback" which covers Chinese characters. I switch which list is used depending on platform (UNITY_WINDOWS versus UNITY_ANDROID).
    2. Then, I took the TMP_FontAsset I use for Chat and Player names and I programmatically add the system fonts listed in step 1 as the fallbackFontAssetTable fonts.
    3. Any English glyphs coming in through chat will use my TMP_FontAsset and any Chinese characters coming in will fallback to the system font.
    Here's some sample code, I've stripped out the list of fallback font names to only look for simsun.ttc just to make the code simpler (this fallback only works on Windows and fallsback for Chinese Characters):

    Code (CSharp):
    1.  
    2.         List<TMP_FontAsset> fallbackFontAssets = new List<TMP_FontAsset>();
    3.  
    4.         // Generate fonts for the systems fonts we know want. Hardcoded for this example.
    5.         string[] fontPaths = Font.GetPathsToOSFonts();
    6.         foreach (string fontPath in fontPaths)
    7.         {
    8.             if (fontPath.Contains("/simsun.ttc")) //On windows 10 this font supports Chinese
    9.             {
    10.                 // Create new Font using one of those paths.
    11.                 Font osFont = new Font(fontPath);
    12.                 // Create new font asset using this OS font.
    13.                 fallbackFontAssets.Add(TMP_FontAsset.CreateFontAsset(osFont));
    14.             }
    15.         }
    16.  
    17.         //Assign the fallback font assets to the fonts that need it.
    18.         fontAsset.fallbackFontAssetTable = fallbackFontAssets;
    19.        
    Now, any text that uses the "fontAsset" that had the fallbackFontAssetTable assigned will default to using simsun.ttc if a gylph can't be found within the original fontAsset. Obviously, the simsun.ttc check would have to be different for Android and iOS since simsun is a Windows 10 OS Font.
     
    Last edited: Aug 13, 2020