Guide

Text and languages

The engine has its own text stack, from Unicode data to glyph pixels. Text in any language is shaped, broken into lines and drawn the way a browser does it.

Fonts

Fonts come from font-family and @font-face. Put the file in Assets/Resources/DevCoreUIEngine/Fonts and name it by URL:

App.css
@font-face {
    font-family: "Title";
    src: url(Fonts/Title-Bold.ttf);
    font-weight: 700;
}

h1 { font-family: "Title", sans-serif; }

Store the file with a .bytes ending (Title-Bold.ttf.bytes) so that Unity keeps the font's own bytes; the URL is written without it.

Fallback, character by character

When the fonts you named do not have a character, the engine looks further, per character, in this order:

  1. Your game's font packs for the character's script or language.
  2. The platform's choice. On Windows this is what Chromium picks, measured over 30,000 characters.
  3. System fonts for the script, then any installed font that has the glyph.

The lang attribute picks the right CJK glyph variants (ja, zh-Hans, zh-Hant, ko). Emoji come from a color font. When nothing has the character, a hollow box is drawn.

Font packs

A Font Fallback Settings asset (Assets → Create → DevCore UI → Font Fallback Settings) lists fonts per script, by ISO 15924 code: Arab, Hebr, Deva, Thai, Hans, Hant, Jpan, Kore, Emoji, Symbols, Math, Default. It also says whether system fonts may be used.

WebGL and consoles have no system fonts to fall back on: ship packs for every script your game shows, including Default.

Shaping

Shaping turns characters into positioned glyphs: joining Arabic letters, reordering Indic vowels, stacking marks. The engine's shaper is a C# port of HarfBuzz and gives identical output (glyphs, clusters, positions) to HarfBuzz 14.5.0 on 20,000 test texts in 38 scripts.

ShaperScripts
ArabicArabic, Persian, Urdu, Syriac; presentation-form fallback for fonts without OpenType tables
HebrewHebrew, with marks
IndicDevanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam
South-East AsianThai, Lao, Khmer, Myanmar
HangulKorean
UniversalTibetan, Javanese, Balinese and the other scripts of the Universal Shaping Engine
DefaultLatin, Greek, Cyrillic, CJK and everything else, with kerning and ligatures

Unicode

The data is Unicode 17.

Glyphs

The engine rasterizes glyphs itself, filtered like DirectWrite's grayscale text, into a shared atlas. There are two kinds:

KindBest for
BitmapText that keeps its size: sharp, pixel for pixel like a browser
Distance field (SDF)Text that is scaled, rotated or animated, and world panels: one glyph serves every size

-devcore-text-rendering: auto (the default) uses bitmaps unless the text is transformed. Set sdf for text whose size animates.

Text that changes every frame

A timer or a score written as {time:F1} makes no string: digits are written straight into the page, only that line is laid out again, and only the glyphs that changed are painted. From code, Text.SetData takes a ReadOnlySpan<char>.

Use font-variant-numeric: tabular-nums on timers so digits keep their width.