TypeFlow Pro
Correct, animated Arabic / Hebrew / right-to-left text for TextMeshPro — plus a pure-C# OpenType engine for the scripts, fonts and effects TMP's atlas can't reach. No migration, no native binaries.
⚡ Arabic in 10 seconds
Add TypeFlow Text to a TMP object — correct joining and RTL order, instantly.
🎬 RTL-aware animation
A typewriter that reveals in logical reading order, plus 20 built-in behaviors, per-word appearances and dialogue actions.
🔥 Kiln engine
Pure-C# OpenType: GSUB/GPOS, variable fonts, color emoji, SDF/MSDF — no TextMeshPro.
✅ 100% conformance
Grapheme, word and sentence segmentation at 100% on the official Unicode suites.
🎨 Families & links
Font families with faux-bold/italic, clickable <link> regions, gradients.
⤓ Drop-in install
Import, run Setup, add a component. Remove it and you're back to vanilla TMP.
This guide covers both tiers. Tier-1 (TextMeshPro) topics come first; the pure-C# Kiln engine follows; shared concepts and reference are at the end.
Installation
Import once, run the Setup wizard, add a component.
In
Window → Package Manager → My Assets, download and import TypeFlow Pro. It lands at Assets/TypeFlowPro/.Window → TextMeshPro → Import TMP Essential Resources (needed for the Tier-1 TextMeshPro path).Tools → TypeFlow Pro → Setup — it verifies TMP and helps you build an Arabic-capable font atlas (it lists the presentation-form ranges to include).TypeFlow Text on a TMP object for the Tier-1 path, or Kiln Text for the standalone Tier-2 renderer.
Requirements
- Unity 2021.3 or newer (developed on Unity 6000.0).
- TextMeshPro (
com.unity.textmeshpro) for the Tier-1 path. - An Arabic-capable font with presentation forms for Tier-1 (e.g. Noto Naskh Arabic, Amiri, Cairo, Dubai). A bundled SIL OFL font (Amiri) is included for the demo.
What gets installed
Assets/TypeFlowPro/
Runtime/ // Unicode (BiDi, segmentation, layout), Fonts (shaping/render),
// Core (pipeline + TypeFlowText), Kiln (Tier-2), TypeFlow (animation)
Editor/ // Setup Wizard, Font Diagnostics, Conformance Runner, inspectors
Demos/ // bundled Amiri font + a guided, interactive showcase scene
// (every feature, page by page) you can open and play
Documentation/ // You are here
Tests/ // EditMode + PlayMode (run headless via Unity -runTests)Project
ITextPreprocessor — disable or remove the component and your text reverts to plain TextMeshPro. Nothing is rewritten on disk.Quick Start: Arabic on TextMeshPro
Correct, joined, right-to-left Arabic on your existing TMP objects — in about ten seconds.
A TextMeshPro - Text (UI) or TextMeshPro (3D), as usual. Assign an Arabic-capable font asset.
Add Component → TypeFlow Pro → TypeFlow Text.That's it — letters join, the line orders right-to-left, and mixed numbers/English are placed correctly.
Add TypeFlow Animator and enable the typewriter — it reveals in logical reading order, correct even for RTL.
BaseDirection.Auto uses the UAX #9 first-strong rule; set RightToLeft or LeftToRight for a fixed layout.Quick Start: Kiln Engine (Tier 2)
Render any font with its own OpenType tables — no TextMeshPro, no native code.
Drop a
.ttf/.otf into your project and rename the extension to .bytes (so Unity imports it as a TextAsset).Add Component → TypeFlow Pro → Kiln Text (Tier 2) on an empty GameObject (it adds a MeshFilter + MeshRenderer).Drag the
.bytes font into the Font slot and set the text. Kiln shapes it with the font's GSUB/GPOS, rasterizes glyphs to its SDF atlas, and draws with the KilnSDF shader.Set Max Width (> 0 enables word wrap) and the alignment. See Kiln Text for all fields.
How It Works (Tier 1)
A string becomes correct, animated RTL text in one preprocessing pass.
TfpTagParserstrips TypeFlow Pro's own animation tags (keeping TextMeshPro markup).ArabicShaperapplies logical-order contextual joining + lam-alef ligatures.Bidi.Resolvecomputes UAX #9 embedding levels and the visual order.- Mirroring (rule L4) produces the visual string and a VisualToSource cluster map.
- TextMeshPro renders the visual string with its own atlas and shaders.
TypeFlowAnimatorreveals/animates the TMP mesh, using the cluster map so the typewriter follows logical reading order (correct for RTL).
TMPro.ITextPreprocessor, so TMP calls it automatically before layout. There is no second mesh, no extra draw call, and no per-frame allocation in steady state.TypeFlow Text
TypeFlowPro.TypeFlowText — the Tier-1 component. Add it to any object with a TMP_Text.
| Member | Description |
|---|---|
BaseDirection BaseDirection | Paragraph direction: Auto (UAX #9 first-strong), LeftToRight, or RightToLeft. Setter re-processes. |
bool EnableArabicShaping | Toggle contextual joining + lam-alef ligatures. Setter re-processes. |
byte LastParagraphLevel | 0 = LTR, 1 = RTL of the last preprocess. |
ProcessedText LastProcessed | Visual string + cluster map of the last preprocess. |
ParsedText LastParsed | Stripped animation data of the last preprocess. |
event Action TextProcessed | Raised after each preprocess. |
string PreprocessText(string) | ITextPreprocessor entry point (called by TMP). |
void Refresh() | Force TMP to re-run preprocessing. |
Auto-flip alignment (so RTL text right-aligns automatically) is a serialized option on the component.
TypeFlow Animator
TypeFlowPro.TypeFlow.TypeFlowAnimator — the animation driver. Add it alongside TypeFlow Text.
Typewriter
Enable the typewriter to reveal text character-by-character. Because reveal follows the cluster map, Arabic appears right-to-left in the correct order, not backwards. Configure characters-per-second, play-on-enable, and a punctuation pause.
Control & events
| Member | Description |
|---|---|
Play() / Pause() / Skip() / Restart() (alias Replay()) | Typewriter control. |
SetTextAndPlay(string) | Set the label's text (TFP tags allowed) and restart the reveal from the top. |
Continue() | Release a <waitinput> hold so the typewriter resumes (call on player input). |
PlayOut() | Play the disappearance (exit) animation. |
SetTypewriterSound(AudioSource, AudioClip[], volume, pitchJitter, everyN) | Wire a per-character click sound at runtime (random clip + pitch jitter; skip whitespace). |
bool IsPlaying / IsComplete / IsWaitingForInput | Current state. |
float Progress / int VisibleCharacters | Reveal progress (0..1) and the count of revealed characters — for progress bars / gating. |
event Action<int> CharacterRevealed | Fires with the logical index as each character appears. |
event Action<int> WordRevealed | Fires with the word index as each whole word finishes revealing. |
event Action WaitingForInput | Fires once when the typewriter parks at a <waitinput>; call Continue() to resume. |
event Action<string> EventTriggered | Fires when a <event=name> tag is reached. |
event Action TypewriterCompleted | Fires when the reveal finishes. |
event Action HiddenOut | Fires when a PlayOut() disappearance finishes. |
var anim = GetComponent<TypeFlowAnimator>();
anim.WordRevealed += w => { /* sync a voice clip per word */ };
anim.EventTriggered += name => { /* react to <event=name> */ };
anim.WaitingForInput += () => ShowContinuePrompt(); // parked at <waitinput>
anim.TypewriterCompleted += () => AdvanceDialogue();
anim.SetTextAndPlay("Hello <wave>world</wave>!<waitinput> Ready?");
if (Input.GetMouseButtonDown(0)) anim.Continue(); // release the wait
progressBar.fillAmount = anim.Progress; // 0..1
anim.Skip(); // reveal everything nowC#
Common recipes
Dialogue box that waits for input. Use <waitinput> between sentences and call Continue() on a click; WaitingForInput tells you when to show a prompt.
anim.WaitingForInput += () => prompt.SetActive(true);
anim.SetTextAndPlay("Hello, traveler!<waitinput> The road is dangerous.<waitinput> Continue?");
void Update() {
if (anim.IsWaitingForInput && Input.GetMouseButtonDown(0)) {
prompt.SetActive(false);
anim.Continue();
}
}C#
Word-by-word voice / SFX sync. Reveal whole words and react per word.
anim.Reveal = TypeFlowAnimator.RevealUnit.Word;
anim.WordRevealed += wordIndex => PlayBlip(wordIndex);
anim.Restart();C#
Animate shaped Arabic. Behaviors work on the RTL-shaped glyphs — just tag the text; the typewriter still reveals in correct logical order.
arabicLabel.text = "<wave>مرحبا</wave> <rainbow>بالعالم</rainbow>";
// (TypeFlow Text handles shaping/BiDi; TypeFlow Animator animates the result)C#
Different entrance per word. Override the global entrance per span, optionally with its own timing.
label.text = "<appear=pop ease=back>Bounce</appear> <appear=scale dur=0.8>grow</appear> in!";Text
Auto-hide toast (show → hold → vanish). Reveal, then play the disappearance after a delay.
anim.Disappearance = EntranceStyle.FadeIn; // reversed for exit
anim.TypewriterCompleted += () => StartCoroutine(HideAfter(2f));
anim.HiddenOut += () => gameObject.SetActive(false);
anim.SetTextAndPlay("Saved!");
// IEnumerator HideAfter(float s){ yield return new WaitForSeconds(s); anim.PlayOut(); }C#
Animation Tags
Inline tags drive per-character motion. They are parsed before TMP sees the text; any other <...> markup passes through to TextMeshPro.
Hello <wave>world</wave>! <shake a=6 f=20>Danger</shake>
مرحبا <wave>بالعالم</wave>Text
Behavior tags — 20 built-in
| Tag | Effect | Channel |
|---|---|---|
<wave> | Vertical sine wave (travelling per-character). | Position |
<bob> | Vertical bob, all letters in unison. | Position |
<sway> | Horizontal sway, in unison. | Position |
<slide> | Horizontal travelling sway (per-character). | Position |
<float> | Slow elliptical drift. | Position |
<bounce> | Bounce (absolute-value sine). | Position |
<wobble> | Circular sway. | Position |
<wiggle> | Organic 2-D wander. | Position |
<shake> | Energetic multi-sine shake. | Position |
<jitter> | Per-step hashed noise. | Position |
<tremor> | Subtle high-frequency rumble. | Position |
<swing> | Rotate back & forth, in unison. | Rotation |
<dangle> | Travelling wave of rotation. | Rotation |
<pendulum> | Gentle phased swing. | Rotation |
<spin> | Continuous rotation (a ≈ deg/sec). | Rotation |
<pulse> | Scale in/out. | Scale |
<heartbeat> | Sharp scale pulse (a living throb). | Scale |
<rainbow> | Hue cycling. | Colour |
<fade> | Alpha pulses up & down. | Alpha |
<blink> | Alpha toggles on/off. | Alpha |
Close any behavior with its matching tag, e.g. <wave>…</wave>. Attributes: a = amplitude, f = frequency — e.g. <wave a=12 f=3>. Register your own tag in C# with TfpEffects.Register("name", …), or with no code via a Custom Effect ScriptableObject (Create ▸ TypeFlow Pro ▸ Custom Effect) on a TfpEffectRegistrar.
<wave><rainbow>hello</rainbow></wave> both waves and cycles colour. A global default effect (set on the component) applies to any untagged glyph and is replaced — not stacked — where you add an explicit tag.Appearance & disappearance tags
| Tag | Effect |
|---|---|
<appear=pop>…</appear> | Give this span its own entrance (fade, pop, scale, slideup/down/left/right, rotate), overriding the global entrance. |
<appear=pop dur=0.5 ease=back> | Optionally give that span its own duration (dur/d, seconds) and easing (ease/e: linear, back, bounce, elastic, sine, expo, cubic, … with in/out variants). Omit either to inherit the component's global timing. |
<disappear=down dur=0.8>…</disappear> | Give this span its own exit (with optional dur/ease too), played by PlayOut(). |
Pacing & dialogue tags
| Tag | Effect |
|---|---|
<speed=0.5>…</speed> | Change reveal speed for the span. |
<pause=0.4> | Hold the typewriter for N seconds. |
<waitfor=0.4> | Timed hold (same as pause). |
<waitinput> / <waitfor> | Halt the typewriter here until you call Continue() — perfect for dialogue boxes. Fires WaitingForInput. |
<event=name> | Fire TypeFlowAnimator.EventTriggered with name. |
// A dialogue box that waits for the player between sentences
text.text = "Hello, traveler!<waitinput> The road ahead is dangerous.<waitinput> Continue?";
anim.WaitingForInput += () => { /* show a 'press to continue' prompt */ };
// on player input: anim.Continue();C#
RTL, Alignment & Digits
The details that make mixed-direction text look right.
Bidirectional layout
The full UAX #9 algorithm (including directional isolates) orders mixed Arabic/Hebrew/Latin/number runs correctly. Numbers and Latin words embedded in an RTL line stay left-to-right within the right-to-left flow.
Alignment auto-flip
With auto-flip enabled, a paragraph that resolves to RTL right-aligns automatically, matching reader expectation without you toggling alignment per string.
Digit shaping
Optional contextual digit shaping maps ASCII digits to Arabic-Indic or Eastern Arabic-Indic (Persian) forms based on context, so "2026" can render with native digits where appropriate. Kashida justification and Persian/Urdu presentation forms are also supported.
**bold** and *italic* work in your dialogue strings.Kiln Text (Tier 2)
TypeFlowPro.Kiln.KilnText — a world-space text renderer that shapes and draws a font entirely in C#.
Kiln parses a font's own tables (TrueType glyf and CFF/Type2), applies GSUB and GPOS, rasterizes glyphs to an SDF atlas, and draws them with a MeshRenderer + the KilnSDF shader — no TextMeshPro and no native code.
| Field | Description |
|---|---|
| Font Asset | A .ttf/.otf imported as bytes (rename to .bytes). Or call SetFont(byte[]) at runtime. |
| Text | The string to render. Settable via the Text property. |
| Pixel Size / World Scale | Rasterization size and world-unit scale. |
| Color | Tint applied through the KilnSDF material. |
| Base Direction | Auto / LeftToRight / RightToLeft — mixed-BiDi glyphs are reordered with the UAX #9 L2 rule. |
| Script | "auto" (default) detects the script from the text and routes complex scripts (Devanagari, Thai, …) through the full reordering/feature shaper; Arabic/Hebrew/Latin use the Arabic shaper. Force a specific OpenType tag ("arab", "deva", "thai", …) if you need to. |
| Max Width | World-unit line width. 0 = single line; > 0 enables word wrap (full UAX #14 line breaking). |
| Line Height Multiplier / Alignment | Multi-line spacing and Left/Center/Right/Justify alignment. |
Complex scripts, color emoji & variable fonts
Feed Kiln the right font and it just works — the component detects the script and picks the shaper, composites COLR/CPAL color emoji as tinted SDF layers, and can interpolate a variable font's axes at runtime:
var kiln = GetComponent<KilnText>();
// Complex script: auto-detected, conjuncts/marks shaped from the font's GSUB/GPOS
kiln.SetFont(devanagariFont.bytes);
kiln.Text = "नमस्ते"; // the स्त conjunct forms (Script = "auto")
// Color emoji: load a COLR/CPAL v0 font and type emoji — rendered in full colour
kiln.SetFont(emojiFont.bytes);
kiln.Text = "🚀❤🎉";
// Variable font: drive a weight (or any) axis live
kiln.SetFont(interVariable.bytes);
if (kiln.HasVariableAxes) kiln.SetVariation("wght", 700f); // re-interpolates & re-rasterizesC#
Inline effects
Kiln understands the same inline effect tags as the Tier-1 style parser, applied to the glyphs it shapes:
| Tag | Effect |
|---|---|
<gradient=RRGGBB,RRGGBB>…</gradient> | Per-glyph vertical gradient (top colour, bottom colour) baked into the mesh vertex colours — works on shaped Arabic/complex text too. |
<outline=RRGGBB,width>…</outline> | Outline ring via the KilnSDF material (applied to the text run). |
<shadow=RRGGBB,dx,dy>…</shadow> | Drop shadow via the KilnSDF material (applied to the text run). |
Tags are stripped before shaping, so they never render as literal text. Example: <gradient=FF4040,FFD23E>سلام</gradient> renders joined Arabic with a red→gold vertical gradient on each letter.
Scripts & Fonts
What the engine shapes today, and the OpenType features behind it.
Contextual joining, ligatures, mark positioning, full BiDi.
Han/Kana rendered from the font's own tables.
Reordering + conjunct formation (e.g. नमस्ते).
Consonants + above/below marks, with dictionary word-breaking.
OpenType features supported
- GSUB: single, multiple, ligature, chaining-context, and extension lookups.
- GPOS: pair, mark-to-base, mark-to-mark, cursive, and extension lookups.
- Variable fonts:
fvaraxes +gvardeltas. - Color: COLR/CPAL color glyphs (e.g. emoji) composited as tinted SDF layers.
- Outlines: TrueType
glyf(incl. composites) and CFF/Type2; SDF + MSDF rasterization; multi-page atlas. - Fallback: automatic per-codepoint font fallback across a chain.
- Collections:
.ttcTrueType collections (by font index).
Families, Links & Effects
Rich-text building blocks that work across both tiers.
Font families
Create a Font Family asset (Assets → Create → TypeFlow Pro → Font Family) holding Regular / Bold / Italic / Bold-Italic faces plus optional fallbacks. <b>/<i> then pick the correct face, with CSS-style graceful degradation (faux-bold / faux-italic when a face is missing).
// Whole-text: set the right face + faux style for a bold/italic state
family.ApplyTo(myTmpText, bold: true, italic: false);
// Mixed text: rewrite <b>/<i> into per-run <font> spans
string markup = family.ToTmpMarkup("plain <b>bold</b> text");C#
Clickable links
The easiest path is the TypeFlow Clickable Text component (Add Component → TypeFlow Pro → TypeFlow Clickable Text) on any TextMeshPro label: set its Source to text with <link=id>…</link> markup and wire OnLinkClicked in the inspector. It strips the link tags (other markup like <color> passes through), pushes the clean text to the label, and hit-tests clicks and hover for you.
var clickable = label.gameObject.AddComponent<TfpClickableText>();
clickable.Source = "Visit the <link=home>home page</link>.";
clickable.OnLinkClicked.AddListener(id => { /* the user clicked link 'id' */ });
clickable.LinkHovered += id => { /* hovered link id, or null */ };C#
Under the hood it uses the pure-geometry primitives, which you can also call directly (e.g. for a Kiln layout):
string clean = LinkParser.Parse(source, out var links);
// boxes from TextMeshPro (or your Kiln layout):
var boxes = LinkHitTester.BoxesFromTextMeshPro(tmpText);
string id = LinkHitTester.GetLinkIdAt(localPoint, boxes, links);
if (id != null) { /* the user clicked link 'id' */ }C#
Inline effect tags
StyleTagParser parses these into style spans applied by the Kiln SDF renderer. Gradients apply via per-glyph vertex colours; the rest are computed in the KilnSDF shader (crisp at any size, resolution-independent, ~free, WebGL-safe). All tags nest and stack, and work on any script including Arabic/RTL.
| Tag | Effect |
|---|---|
<gradient=RRGGBB,RRGGBB> | Per-glyph vertical colour gradient (top, bottom). |
<outline=RRGGBB,width> | SDF outline ring. |
<shadow=RRGGBB,dx,dy> | Soft drop shadow (UV offset). |
<glow=RRGGBB,intensity,radius> | Soft outer halo / neon glow from the distance falloff. |
<longshadow=RRGGBB,dirX,dirY,length> | Solid directional long-shadow streak (flat/retro). |
<bevel=intensity,width,angle> | Faux-3D emboss lit from the SDF gradient (raised/engraved look). |
Example: <outline=101018,0.1><bevel=1.6,0.2,120>STEEL</bevel></outline> or <glow=39E6FF,2.2,0.4>NEON</glow>. See the SDF Effects page in the showcase.
Damage Numbers
Pooled, animated floating combat text — built on the same per-character engine as the rest of TypeFlow Pro, so it does things a generic popup system can't: per-digit entrances, live behaviors, and RTL Arabic-Indic / Persian numbers.
Spawn a number with one call. The first call lazily creates a persistent world-space manager; for full control, drop a TfpDamageNumberManager in your scene or assign your own to TfpDamageNumbers.Default.
using TypeFlowPro.CombatText;
// One-liner — a pooled popup floats up at a world point and fades out:
TfpDamageNumbers.Spawn(150, hitPoint);
// With a no-code style asset (Assets ▸ Create ▸ TypeFlow Pro ▸ Combat Text Style):
TfpDamageNumbers.Spawn(critDamage, hitPoint, critStyle);
// Your own manager — world or canvas, follow a moving enemy, combine rapid hits:
manager.Spawn(heal, enemy.position, healStyle, follow: enemy.transform);C#
The popup style asset
A TfpPopupStyle is a ScriptableObject that defines the whole look — no code. Hand it to Spawn. (Leave it out and the manager uses a sensible default.)
| Field group | What it controls |
|---|---|
Font, FontSize, FontStyle, Color | Rendering. ColorByValue + a ValueGradient make bigger hits glow hotter. |
Abbreviation, Decimals, ThousandsSeparator | Number formatting: metric abbreviation (1234567 → 1.2M), grouping, fixed decimals, plus a Prefix/Suffix. |
Digits | Western, ArabicIndic (٠-٩) or Persian (۰-۹) — combat text in the player's own numerals. |
Lifetime, Rise, RiseDistance, ArcHeight, Direction | How it travels: straight Up, a Directional drift, or a parabolic Arc (loot/XP toss). |
StartScale, ScaleEase, PopInFraction, EndScale | The pop-in (use an OutBack ease for overshoot) and an optional shrink as it dies. |
FadeInFraction, FadeOutFraction | The transparency in/out windows. |
ShakeAmplitude, ShakeFrequency, SpinDegrees | The classic crit shake and optional spin. |
PerCharacter, EntranceStyle, ContinuousEffect | Animate each digit independently with the TypeFlow engine — a staggered entrance plus a continuous behavior (Wave, Rainbow…). |
Combine, CombineRadius, CombineWindow | Merge rapid hits in the same spot into one rising total (DPS-meter feel) instead of overlapping popups. |
FaceCamera | Billboard world-space popups toward the camera. |
Components & API
| Member | Description |
|---|---|
TfpDamageNumbers.Spawn(value, worldPos, style?, follow?) | Static one-liner; routes to Default (auto-created, persistent, world-space). |
TfpDamageNumberManager | Pools and spawns popups. WorldSpace toggles 3D TextMeshPro (billboarded) vs canvas TextMeshProUGUI under a Container. Prewarm avoids first-hit hitches. |
TfpDamageNumber | One pooled popup. Drives a TMP_Text through its life; exposes Value, DisplayText, IsAlive. |
TfpPopupStyle | The no-code style asset (above). BuildFormat() / BuildMotion() compile its fields into the pure structs the runtime uses. |
TfpNumberFormat.Format(value, fmt) | Pure, culture-invariant value→string (abbreviation, grouping, decimals, prefix/suffix, digit substitution). Reusable on its own. |
TextMeshPro, billboarded). Set WorldSpace = false and a Container under a Canvas for HUD/screen-space popups instead — the same Spawn call drives both. It's all C#, AOT-safe, and pools every instance so steady combat allocates nothing.TfpPopupStyle built in a few lines.3D & more
Further v4 capabilities — most have a live page in the bundled showcase to try.
| Feature | What it does & how |
|---|---|
3D extruded text — KilnText3D | TRUE 3D geometry extruded from ANY OpenType font in pure C# (face + sides + depth/bevel, separate submeshes/materials). Runs the same shaper, so Arabic joins in 3D and complex scripts shape; Built-in/URP/HDRP + WebGL. k3d.SetFont(bytes); k3d.Text = "نص"; k3d.Depth = 0.2f; |
Text decal API — TfpTextDecal | Experimental mesh-projection component for shaped text on 3D surfaces. The runtime code and tests are present, but this is not currently a main showcase page; verify it on your target surfaces and pipeline before using it in marketing screenshots. |
| Curved / path text | Bend the baseline along an AnimationCurve: anim.ShapeCurve + ShapeAmplitude (+ ShapeScrollSpeed to travel), or wrap into a ring with ShapeRadial + ShapeRadius. Composes with behaviors/typewriter; Arabic/RTL too. |
| SDF text effects | New inline tags <glow>, <longshadow>, <bevel> (see Inline effect tags) — crisp, per-glyph, resolution-independent, in the Kiln SDF shader. |
RTL one-call converter — TypeFlowRtl.Convert | One call shapes + bidi-reorders logical text to a TMP-ready visual string — a drop-in migration path from "RTL fixer" plugins. No component needed. |
| Reduce-motion (a11y) | Global switch TypeFlowAnimator.ReduceMotion = true instantly settles all animated text (events still fire) for motion-sensitive players. |
Pixel-perfect — KilnText.PixelPerfect | Snaps each glyph quad to the pixel grid for crisp small text / pixel-art (no sub-pixel shimmer). |
Two-Tier Architecture
One package, two ways to put correct text on screen.
| Tier 1 — TextMeshPro | Tier 2 — Kiln | |
|---|---|---|
| Renderer | TextMeshPro (its atlas + shaders) | Pure-C# OpenType engine + KilnSDF shader |
| Migration | None — add a component | New component (Kiln Text) |
| Best for | Arabic/Hebrew/RTL UI & animation | Scripts/fonts/effects TMP can't express |
| Native code | None | None |
| Animation engine | Yes (typewriter + behaviors) | Shares the same building blocks |
The two tiers share the same Unicode foundation (BiDi, segmentation, shaping) — a clip of Arabic text shapes identically whether TMP or Kiln renders it.
Included vs Scope
A buyer-facing map of what ships in this package, what needs your own project assets, and what TypeFlow Pro does not try to be.
| Area | Status | Details |
|---|---|---|
| TextMeshPro Arabic / Hebrew / RTL | Included | TypeFlow Text plugs into existing TMP UI and 3D objects for Arabic shaping, UAX #9 BiDi, mixed Latin/numbers, digit shaping and alignment auto-flip. |
| RTL-aware text animation | Included | Typewriter reveal, word reveal, 20 built-in behavior tags, appear/disappear tags, dialogue waits, callbacks, per-character sound and reduce-motion support. |
| Kiln pure-C# OpenType renderer | Included | Standalone MeshRenderer path for advanced font rendering: TrueType/CFF outlines, GSUB/GPOS shaping, variable fonts, COLR/CPAL color emoji, SDF/MSDF, outlines, shadows, gradients and pixel snapping. |
| Game text extras | Included | Clickable links, font families, Markdown conversion, font fallback APIs, damage numbers, 3D extruded text, auto-size, wrapping and ellipsis helpers. A text-decal API is present but should be project-verified before being treated as a headline feature. |
| Editor tools | Included | Setup Wizard, Font Diagnostics and Conformance Runner under Tools → TypeFlow Pro. |
| Fonts | Demo font included | Amiri is bundled for the Arabic demo under the SIL OFL. For production language coverage, use fonts you have the rights to ship, especially for CJK, emoji and project-specific brand typography. |
| Render pipelines | Supported | Built-in Render Pipeline, URP and HDRP are supported for the main text/UI/Kiln paths. |
| Online services / AI | Not included | TypeFlow Pro is not an AI generator, translation service, localization database, account system or cloud tool. It has no API keys, no subscription and no runtime internet requirement. |
| Native plugins | Not used | No HarfBuzz, FreeType or platform-specific binary plugin is bundled. The package is pure C# plus Unity shaders/components. |
| Every rare script/font edge case | Active scope area | Arabic, Hebrew, CJK, Devanagari and Thai have validated paths. Myanmar/Khmer and some advanced per-font shaping edge cases remain areas to verify with project fonts. |
Unicode Conformance
Measured against the official Unicode test suites and enforced by regression-floored tests.
| Official suite | Result | What it proves |
|---|---|---|
| GraphemeBreakTest | 100% | User-perceived character boundaries (emoji ZWJ, etc.). |
| WordBreakTest | 100% | Word boundaries (incl. flag pairs, Hebrew quotes). |
| SentenceBreakTest | 100% | Sentence boundaries. |
| BidiCharacterTest | 99.97% | The bidirectional algorithm over 91,707 official cases. |
| LineBreakTest | 99.73% | UAX #14 line-break opportunities. |
Reproduce them yourself: run the UnicodeConformanceTests and BidiCharacterConformanceTests headlessly. Each test prints its pass rate and asserts a regression floor, so conformance can't silently slip.
Editor Tools
Under Tools → TypeFlow Pro.
Verifies TextMeshPro and helps build an Arabic-capable atlas, listing the required Unicode ranges.
Scans a TMP font asset and reports missing Arabic base/presentation glyphs.
Runs the bundled UAX #9 BiDi vectors and shows pass counts.
Scripting API
The stable public surface. Namespaces: TypeFlowPro, TypeFlowPro.Unicode.BiDi, TypeFlowPro.Fonts.Shaping, TypeFlowPro.TypeFlow.
Common usage
using TypeFlowPro;
using TypeFlowPro.Unicode.BiDi;
var tfp = GetComponent<TypeFlowText>();
tfp.BaseDirection = BaseDirection.Auto;
tfp.EnableArabicShaping = true;
tfp.Refresh();C#
Pipeline & BiDi (engine-level)
// One-shot processing without a component:
ProcessedText p = TypeFlowProcessor.Process(logical, ShapeSettings.Default);
// p.Visual, p.ParagraphLevel, p.VisualToSource, p.IsRightToLeft
// Raw bidirectional resolution:
BidiResult b = Bidi.Resolve(text, BaseDirection.Auto);
// b.ParagraphLevel, b.Levels, b.VisualToLogicalC#
Key types
| Type | Purpose |
|---|---|
TypeFlowProcessor.Process(string, ShapeSettings) | Logical → visual string + cluster map. |
Bidi.Resolve(string|int[], BaseDirection) | UAX #9 levels + visual order. |
ArabicShaper.Shape(int[]) | Contextual joining → glyphs + source map. |
TfpTagParser.Parse(string) | Clean text + animation spans/events/controls. |
KilnText.SetFont / Text / Script / SetVariation(tag,value) | Tier-2 renderer: load a font, set text, force/auto a script, drive a variable-font axis (HasVariableAxes / VariationAxes). |
TypeFlowProcessor.ProcessBatch(string[], ShapeSettings) | Shape many strings in parallel (multi-core, thread-safe, cache-free). |
KashidaJustifier.InsertKashidas(int[] cps, int count) | Distribute Arabic tatweel elongations at the best joints for kashida justification. |
FontFallback.SegmentRuns(int[] cps) | Resolve a mixed-script string into per-font runs across an ordered font chain. |
RevealScheduler / TextBehaviors / AnimationMap | Animation building blocks. |
FontFamily / FontFamilyResolver | Face selection + faux synthesis. |
TfpClickableText | Drop-in clickable/interactive text component (click + hover on <link> regions). |
LinkParser / LinkHitTester | Clickable-text parsing + hit-testing primitives (used by the component). |
Troubleshooting
The issues that come up most, and how to fix them.
Arabic shows as disconnected / boxed letters
The font atlas is missing Arabic presentation forms. Run Tools → TypeFlow Pro → Setup and rebuild the atlas with the presentation-form ranges it lists, using an Arabic-capable font (Noto Naskh Arabic, Amiri, Cairo, Dubai). Use Font Diagnostics to confirm the glyphs are present.
Arabic appears backwards
Make sure the TypeFlow Text component is actually on the object (the TMP field alone won't reorder). If direction detection is wrong for your data, set BaseDirection to RightToLeft explicitly instead of Auto.
Mixed numbers/English sit in the wrong place
That ordering is governed by the bidirectional algorithm and is usually correct per UAX #9. If a specific string looks wrong, check whether you intended a fixed paragraph direction — setting BaseDirection explicitly removes the first-strong ambiguity.
The typewriter reveals RTL text in the wrong order
Use TypeFlow Animator (not a generic typewriter asset). It reveals via the cluster map in logical reading order, which is correct for RTL. Generic per-glyph typewriters reveal in visual order and look backwards on Arabic.
Kiln Text renders nothing
Confirm the font is imported as bytes (extension renamed to .bytes so it's a TextAsset) and assigned to the Font slot, and that the GameObject has the MeshFilter + MeshRenderer the component requires. Check the Console for font-parse messages.
A complex script doesn't shape correctly in Kiln
Latin, Arabic, Hebrew, CJK, Devanagari and Thai are validated; Myanmar/Khmer cluster reordering is not yet modeled. Also confirm the font actually contains the GSUB/GPOS features for that script — Kiln shapes from the font's own tables.
FAQ
Quick answers to the questions that come up most.
Do I have to migrate off TextMeshPro?
No. TypeFlow Text is an ITextPreprocessor — add it to your existing TMP objects and they start rendering correct Arabic/RTL. Remove it and you're back to vanilla TextMeshPro, with nothing rewritten.
Does it use native plugins?
No. Everything is pure C#. It runs on every Unity target including WebGL and consoles, with no per-platform native libraries (both WebGL and Windows-IL2CPP builds are verified clean).
Is TypeFlow Pro an AI or cloud service?
No. TypeFlow Pro is a local Unity text-rendering and animation toolkit. It does not generate translations, call an online AI model, require API keys, use credits, or need a runtime internet connection.
Which languages are supported?
Tier 1 (TextMeshPro): Arabic, Persian/Farsi, Urdu and other Arabic-script languages, plus Hebrew, with full BiDi for mixing them with Latin, numbers and punctuation. The Tier-2 Kiln engine additionally render-validates CJK, Devanagari (conjuncts) and Thai. Myanmar/Khmer cluster shaping is on the roadmap.
Does the typewriter work in Arabic?
Yes — it reveals in logical reading order using the cluster map, so Arabic appears right-to-left in the correct order, not backwards. This is a common bug in animation assets; TypeFlow Pro handles it.
Do rich-text tags (<color>, <b>) still work?
Yes. TextMeshPro tags pass through untouched; only TypeFlow Pro's own animation tags are consumed. (Deep interaction of arbitrary TMP markup inside reordered RTL runs continues to be hardened.)
What about performance?
Shaping is cached and only re-runs when the text changes; animation manipulates the existing TMP mesh with no per-frame allocations in steady state. No extra draw calls or materials. A multi-core batch API is included for processing many strings at once.
Does it work at runtime / in builds?
Yes. Both tiers run at runtime on any Unity build target. There is no editor-only dependency for rendering.
Support
Need help? We're here for you.
Get in Touch
Bug reports, feature requests, font/shaping questions — reach out and we'll get back to you.
✉ szekipapa77@gmail.comWe typically respond within 24–48 hours.
- Check the Troubleshooting section
- Run Font Diagnostics for missing-glyph issues
- Confirm the TypeFlow Text component is on the object
- Check the Console for parse/shaping messages
- Unity version (e.g.
6000.0.30f1) - TypeFlow Pro version (v4.0)
- Render pipeline (Built-in / URP / HDRP)
- The font you're using + a sample string
Licenses & Notices
Everything legal in one place. The same notices ship as plain text in Third-Party Notices.txt at the package root, with the font licence also at Demos/Fonts/Amiri/OFL.txt.
TypeFlow Pro © 2026. All rights reserved. When obtained through the Unity Asset Store, your use of this package is governed by the Unity Asset Store End User License Agreement.
The character-property tables used by the bidirectional algorithm and the Arabic shaper are derived from the Unicode Character Database. Use of Unicode data files is governed by the Unicode Terms of Use. Copyright © Unicode, Inc. Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. The tables are generated at author time; the raw UCD files are not redistributed here.
Amiri-Regular.ttf, its AmiriKiln.bytes copy and the generated
Arabic SDF TextMeshPro asset are licensed under the SIL Open Font License 1.1.
Amiri is the only third-party font shipped inside this package. You must supply your own
licensed fonts for production use; the engine renders from any font you provide at runtime.
Copyright 2010-2022 The Amiri Project Authors (https://github.com/aliftype/amiri). This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: https://openfontlicense.org/ ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
HarfBuzz is not included, linked or shipped — it is used in development only as an offline source of golden shaping outputs to cross-check this package's independent pure-C# implementation. The showcase's colour-emoji, world-script and variable-font pages use extra fonts (OpenMoji, Noto, Inter) that are deliberately kept outside the published package; those pages show an "assign a font" note without them.
TypeFlow Pro v4.0 · Built for Unity 2021.3+ · Pure C#, no native binaries
Support: szekipapa77@gmail.com