Unity Text Shows Squares Instead of Characters: Font Fallback That Just Works

Last reviewed

Short answer

Squares, boxes or blank spaces appear when the font asset a text uses has no glyph for a character and nothing in its fallback chain does either. In TextMesh Pro every language needs a font asset with that language's characters, added to a fallback list by hand; reaching operating-system fonts requires dynamic OS font assets set up in advance.

UniText falls back to the operating system's own fonts automatically. For each text run it asks the platform for a font that covers that run's language, so text in any language renders on desktop and mobile even when the project ships a single Latin font.

Why characters turn into squares

  • The font has no glyph for the character, which is common for Chinese, Japanese, Korean, Thai, Arabic and Indic text in a game font designed for Latin.
  • The character exists in the font but was not baked into a static atlas, which often happens with user names, chat and other text the game did not know in advance.
  • The fallback chain does not include a font for that script, or the fonts are listed in an order that picks the wrong one first.
  • The character is part of an emoji sequence or a combining mark that the text engine does not process as a unit.

TextMesh Pro looks for a glyph in a fixed order: the primary font asset, its fallback list, the sprite asset, the general fallback list in TMP Settings, the default sprite asset and the default font asset. When all of them miss, it draws the missing-glyph character, a □ by default. Operating-system fonts take part only as Dynamic OS font assets that someone creates and adds to a fallback list. Dynamic font assets avoid baking atlases, but their source fonts are included in builds.

Shipping a full font for every script fixes coverage at a price: a complete CJK font holds tens of thousands of glyphs and runs to many megabytes, and each language adds another file to the build and another entry to every fallback list.

How UniText avoids missing characters

  • Automatic system fallback. Any character no font in the stack covers is rendered from an operating-system font, chosen by the platform's own font matcher for that run's language: DirectWrite on Windows, CoreText on Apple platforms, AFontMatcher on Android and fontconfig on Linux. It is on by default.
  • Language-aware Han forms. The Language property or a <lang=zh-Hans> range selects Chinese, Japanese or Korean glyph shapes for the same code point through the OpenType locl feature and a font family that prefers that language.
  • No baked atlases. Glyphs are rasterized the first time text displays them, so user-generated text never meets a character that was left out of an atlas.
  • Smaller fonts when you do ship them. Font bytes are Zstd-compressed into the font asset, the Font Subsetter strips unused glyphs, and large font files are read from disk on demand through Font Memory Mapping instead of being loaded whole into memory.

WebGL is the exception: browsers do not give WebGL access to system fonts, so a WebGL build assigns font assets for the languages it shows, or supplies font bytes at runtime with UniTextFont.CreateFontAsset(byte[]).

Questions

Does system-font fallback work in the Editor and in builds?

Yes, on Windows, macOS, Linux, Android and iOS. It can be turned off in Project Settings › LightSide › UniText › Fonts › Disable System Font Fallback for projects that must render only their own fonts.

Can I still choose my own font for a language?

Yes. Fonts in the component's font stack always come first, and a font family can declare the language it prefers, so Japanese text picks your Japanese font while other languages fall back to the system.

How do I keep CJK fonts out of the build?

On desktop and mobile, rely on system fallback and ship no CJK font at all. If you need a specific design, subset the font to the characters your text uses and load it from a server at runtime.

Check it in your project

Run the browser demo, follow the setup guide, or compare the free version with the licenses.

Related problems