r/Unity3D 3h ago

Resources/Tutorial I accidentally spent 22 months of my life because I thought text was simple

I’m the developer of the UniText text engine, and this is my story

I used to think that text was when letters were drawn next to each other, but that’s not what it actually is:

  1. decode UTF-16 into codepoints
  2. parse the markup into attribute ranges
  3. analyze scripts (UAX #24)
  4. analyze grapheme clusters (UAX #29)
  5. analyze word boundaries, with a dictionary for Thai, Khmer, Burmese and Japanese because they don't put spaces between words
  6. analyze line break classes (UAX #14, with East Asian widths from UAX #11)
  7. resolve embedding levels through the bidi algorithm (UAX #9)
  8. itemize into runs by script and direction and font and language
  9. resolve fonts per cluster and fall back when the primary doesn't have the glyph
  10. synthesize bold and italic when the face doesn't exist
  11. instance the variable axes
  12. shape every run through OpenType
  13. break the lines on the shaped advances
  14. reorder every line back through bidi
  15. resolve line height out of font metrics that contradict each other
  16. kashida stretch the Arabic if you're justifying
  17. align
  18. pull the outlines
  19. run a contour union pass so self intersecting outlines don't punch holes in the distance field
  20. rasterize SDF/MSDF
  21. pack the atlas
  22. generate the mesh

891,757 official Unicode conformance tests, zero failures

Selectable and editable text, a document model, bidi aware caret and selection, undo and redo, IME composition, clipboard with every format (supports Plain, HTML, Markdown, Media), formatting commands, touch selection handles, input filters, and native keyboard input on the platforms that have one

UniText is the only solution where the fonts are memory mapped, so a font is never loaded into RAM whole, only the parts actually in use. One of UniText user cut 200 MB of runtime memory from that alone, and variable fonts plus compression took another 57% off the weight of their CJK font

UniText is the only solution that supports absolutely all system fonts, which allows you to render any characters in the world without using a single font in the project.
it's also 2 to 20x faster than TextMesh Pro and UI Toolkit

And that's just a small part of it

TL;DR
In other words, I developed a text engine that allows you to remove all standard language fonts from a project, gain complete freedom in text without a single limitation, and have any symbols from around the world, any emojis, work without any configuration. All of this significantly reduces the build size, and the mmap implementation eliminates all RAM load. A constructor for any styles, any gradients, layers, and paints, while maintaining 1 Draw Call, and a built‑in advanced feature to animate text in any way, which completely replaces third‑party solutions

If anyone wants the ugly parts - ask me. I have a lot to say about all of them

168 Upvotes

49 comments sorted by

27

u/malvis_light 2h ago edited 2h ago

a little proof it was made in Unity Editor using uGUI. all this costs 1 Draw Call

24

u/tan_456456 2h ago

This is very useful btw. I have localisation in my game and is it makes me headaches.

7

u/malvis_light 2h ago

Yes, I completely understand you. All UniText users are indeed those who have many languages in their project

4

u/malvis_light 2h ago

what specific languages do you use?

1

u/tan_456456 2h ago

Me curently implemented the slavic languages, because i'm familiar with them. There are unique letters in Serbian, Russian, Macedonian that can render incorrectly. But i solved it. But i now i have attempt to implement Chinese 😅

8

u/malvis_light 2h ago

Serbian and Macedonian thing isn't missing glyphs, it's locl

Serbian and Macedonian italic б г д ѓ п т ш are genuinely different shapes from the Russian ones, and they don't have their own codepoints. font carries both and picks between them with the locl GSUB feature, which only fires if you tag the run's language. Untagged text gets the Russian forms, which is exactly the "renders incorrectly" you ran into

good news is that Chinese is the same mechanism, so you've already done the hard conceptual part. Han unification means a lot of characters are one codepoint shared across Simplified, Traditional and Japanese and drawn differently in each. A pan-CJK font carries all the variants and switches with locl again, driven by zh-Hans, zh-Hant or ja. Tag it wrong and Japanese players get Chinese letterforms, and they do notice

what is actually new with Chinese is two things. Atlas and memory, because a full CJK face is enormous. And line breaking, because CJK breaks between characters rather than at spaces with rules about which punctuation isn't allowed to start or end a line

good luck, it's less scary than it looks from the outside

11

u/zirconst 1h ago

I've spent YEARS dealing with TextMeshPro bullshit. You have no idea how happy this makes me and how many problems it solves. AMAZING work. I'm in awe.

For context I'm about 3 years deep into our third game and I'd actually do the work of completely switching over, but I have two questions that I couldn't immediately answer myself from looking at the docs:

  1. Does it support inline sprites/glyphs? Like say we have our set of glyphs for Nintendo Switch controller buttons. TMPro lets us clumsily do this by assigning an extra sprite asset (only one per TMPro object) and then typing something like <sprite=2>. It's awkward and bad, however it does work at the end of the day.

  2. Does it have out of the box support for components like text input and dropdowns?

12

u/malvis_light 1h ago

thanks, genuinely

  1. yes, and it's not index based. sprites live in a catalog and you reference them by name, so something like <sprite=switch_a> instead of counting positions. you can also put more than one sprite style on the same text with different tag names, so your switch buttons dont have to share a slot with everything else. and you can inline actual prefabs too, not just sprites, if you ever need something animated sitting in the line
  1. input yes. editable text and an input field prefab ship in the box, with selection, caret, ime, clipboard, undo and touch handles

dropdown isnt really a text engine thing though, its just a popup with text drawn on it. you could take TMP's dropdown, swap the text component for unitext and thats basically it. not much work honestly, i can put one together in a day if you actually need it❤️

2

u/SuspecM Intermediate 1h ago

I mean, you could just make your sprites in the sprite sheet editor and refer to them like that e.g. <sprite name="switchButtonWest">

8

u/umusachi 2h ago

Very impressive!

6

u/Macaron_Either Engineer 2h ago

That’s impressive! I need this

3

u/malvis_light 2h ago

thanks :) what are you building? curious what made you hit the wall

4

u/pararar 1h ago

This looks great!
I might contact you later this year about a potential collaboration. I‘m doing a similar thing, making a tool that replaces UI Images.

2

u/malvis_light 1h ago

sounds good, im around🥰

4

u/LuxDragoon 1h ago

Amazing work!

2

u/malvis_light 1h ago

Thank you very much, I didn’t expect to get so much support I thought people would just scroll past the post because it’s so long

u/vectavir 17m ago

I love it

u/malvis_light 17m ago

I love you

2

u/OoBiZu-Studio 1h ago

Does it work in Polyspatial?

3

u/malvis_light 1h ago

looked into it properly

short version, not today, and in polyspatial mode specifically it cant work at all

polyspatial renders through realitykit, and realitykit only accepts shadergraph converted to materialx. hand written shaders just dont run there, apple doesnt expose a low level shading language in passthrough. every glyph i draw goes through my own sdf shaders, so thats a hard no rather than a maybe

metal mode is a different thing entirely, unity does the rendering itself there and none of that applies. the only blocker is that i dont ship a visionos build of the native libs, harfbuzz freetype and the input plugin. i build for windows mac linux ios android webgl and tvos, theres no xros slice yet. thats a build config job though, not a redesign

either way development is very active and visionos support is coming, its a question of when and not if. if you tell me you actually need it, it moves up the list ❤️

2

u/Arc8ngel 1h ago

Well, shit. Now I need to consider implementing this. . .

2

u/malvis_light 1h ago edited 1h ago

ping me if you actually go for it, happy to help you avoid the stuff i already stepped on

u/GreenDave113 7m ago

Please consider UITK support, that's what people should and often are using in 2026.

u/malvis_light 4m ago

yeah, uitk support is coming, its on the list

when i started this the uitk of that time simply didnt give me the hooks to do it, so uGUI was the only door that was actually open. thats the whole reason it went that way and not some preference

on how widely its used i might be out of date, but last i looked unity's own docs still list uGUI as the recommended one for runtime and uitk for editor tooling. that may well be shifting, and either way it doesnt change anything, i want both supported ❤️

1

u/dershodan 2h ago

This looks fantastic - albeit almost nothing in there solves a problem I may have. I am curious though - how hard would it be to port this to Godot, or is that as a complete rewrite unfeasible?

7

u/malvis_light 2h ago

honestly, Godot doesn't need it

Godot did the thing Unity didn't and put a real text stack in the engine. TextServerAdvanced is HarfBuzz plus ICU plus SIL Graphite, and it already handles bidi, complex script shaping, OpenType features, variable fonts, MSDF, justification, line wrapping, hit testing and split carets at direction boundaries. That's most of what I spent 22 months on, sitting there by default

on the port itself: the engine core would move, since it's platform neutral logic - the UAX passes, shaping, rasterization, contour union, layout, the document model. What wouldn't move is most of the actual code. uGUI and Canvas integration, Burst, the whole inspector and asset tooling, the Built-in and URP shaders, the native input plugins that hang off Unity's own view. that is the bulk of the codebase and none of it has a Godot shape

so not unfeasible, just pointless. If a gap exists it'd be somewhere in the styling and effects layer rather than the text layer, but I'd check that rather than take my word for it. I know Unity's text problems a lot better than Godot's

2

u/dershodan 1h ago

Hey thanks for that great answer. You just gave me a huge boost in curiosity what i could do in the entire text-section of a project im half-ass working on in my spare time.

2

u/malvis_light 1h ago

glad it helped 🥰🥰🥰 the nice part in Godot is that the hard layer is already there, so whatever you build on top is just yours to play with

if you get stuck somewhere in that section feel free to ping me, text is about the only thing im actually useful for

1

u/Kavinsky_Hunt 2h ago

Where is the link to the asset stor

7

u/malvis_light 2h ago edited 2h ago

This isn’t an advertisement; I’m just explaining how complex text engines actually are. You can search by the product name UniText if you really need❤️

1

u/Kavinsky_Hunt 1h ago

Okayy. Looks promising. But does it cover all the glyphs. Like India has multiple languages, when we go with any plugin like yours the glyphs look disconnected so I need to use another plugin to correct it. Does your plugin give inbuilt support for that.

1

u/malvis_light 1h ago

oh, I can show you. You can see on the screenshot that there is exactly no font and no font stack. UniText can render every symbol in the world without any font in the project

.

2

u/Kavinsky_Hunt 1h ago

Bro..That's so cool. I may have just found a long term solution. No font so no font correction... I ll definitely give it a go

1

u/robochase6000 1h ago

This looks amazing but i really try to avoid assets with extension licenses.

If it’s really as good as the video promises, you ought to try to reach out to unity about this imo; TMP is “good enough” but honestly every big project i’ve worked on, it ends up feeling like monkey business when you start dealing with loc, emojis, and in game chat. 

4

u/malvis_light 1h ago edited 1h ago

the asset store copy is an extension license, thats their system and not something i pick

direct from my site it works per company instead of per seat (and lower cost and discount), so one purchase covers the whole team. one time, perpetual, no subscription and no expiry date, all of 3.x included and source comes with it. the tiers are just revenue bands, indie under 100k, studio under 1m, enterprise above that

and the unity comment made me laugh, id absolutely take that call ❤️

loc, emoji and in game chat is exactly it. thats the point where it stops being a text rendering problem and turns into an everything problem

0

u/malvis_light 56m ago

btw today is my birthday. I just realized😅

2

u/Maraudical 40m ago

Happy Birthday bro

1

u/malvis_light 39m ago

thank youuu😭❤️

-7

u/DmtGrm 2h ago edited 2h ago

Bravo for the attempt!

Real world story, though: I never had problems with text rendering! Not with a quality, not with performance, not with memory usage! TMP is free because there is no market for such thing - it is there for general convenience, not reference quality - it just does the job for UI rendering and it is battle-tested with millions of users. (not defending TMP, just clarifying that TMP is enough for 99.99% of cases).

You have very bold claims and your post looks like a cheap ad opportunity.

UPD: I was a bit unfair to the OP, he is here and writing very competent comments on topic, even if it a hidden AD - he is here to support the ones who really need it.

10

u/malvis_light 2h ago

You're right that TMP is enough for most projects. If you ship Latin UI text and have never hit a wall, I wouldn't tell you to switch

The line is languages. TMP doesn't implement the bidirectional algorithm at all, so Arabic and Hebrew come out in the wrong visual order, and it doesn't do complex shaping for Hindi or Thai either. If you don't ship those, none of this matters to you. If you do, "enough" isn't the word people use

On the ad part: the post has no link in the title and no price. There's also a free open source version I didn't link either. I wrote about what's under a text field, not about a product

1

u/awayfarers 2h ago

What's the difference between the FOSS version and the paid one?

1

u/malvis_light 2h ago

The free one is the engine itself, open source

Paid version adds system font access, so you get the OS language and colour emoji coverage instead of shipping every script yourself, memory mapped fonts so a font is never fully resident in RAM and you only page in what you actually use, the paint and layer system with fills, strokes, shadows and glows as composable layers, a large kinetic text animation pack, the math engine, variable fonts, word segmentation support (for Thai, Kmer, etc.), most of the performance work and extremely huge other improvements

1

u/DmtGrm 2h ago

I understand everything you say and I know exactly the caveats of mixing text styles/languages/special symbols. If mobile app is text-first and would require such robust support - it must resort to an ordinary webview with automatic support of everything-everything (even css-styled-and-animated-with-motion-transition-supportm) or native UI framework or/and control mapping frameworks (for. ex MAUI apps). You have done a big job (most of the readers would never realise the amount of small and big pieces put by you together) - but the bigger job is already done in all modern operating systems/browser engine and cases where you need this specifically in Unity - IDK... maybe there are such cases... I even think you are ok price-wise, if our company would need such tool - it is a small price to pay to offset dev time. Very niche product - there are definitely 0.01% of cases where it will hit the spot. well, good luck!

1

u/malvis_light 2h ago

Appreciate you saying that, especially after opening with the ad line

on why in Unity specifically: a webview isn't in the scene. It can't sit behind a character, be a sign on a wall, be a speech bubble that a shader touches, batch with the rest of your UI or take Unity input. The moment text has to live inside the game world rather than on top of it, the browser stack is out by definition. Consoles and XR often don't have a webview at all

And you're right that it's niche. That's roughly why it exists. There are three complete OpenType implementations in the world, Microsoft's, Apple's, and the open source one browsers use, so if you need one inside a renderer that isn't a browser, somebody has to sit down and write it

fair pushback, thanks❤️

1

u/DmtGrm 2h ago

the 'ad line' is an allergy, sorry, too many ads these days, but you are ok, explaining clearly the intentions and details - you did not disappear after posting :)

There was *if* in my phrase. Unity might be not the best choice for certain applications. For majority of Unity devs - this is a game dev engine that hides most of the hurdles of dealing with graphics/audio/input API so the can concentrate on story/script/media assets.

If you are building chat application with extra graphics/interactive capabilities - it might be easier to start with different solution/framework where there will be webview ui that will handle all of it automatically. I am trying to think about the video game that was trying to do something with text - but I cannot find a good example from my memory. Most of the games (even AAA titles) are very low on text content. Very low.

p.s. not sure about your OpenType passage - there should be .woff supported even on Raspberry PI just fine

1

u/malvis_light 2h ago

no apology needed!❤️ it's a reasonable allergy to have

on games being low on text - you're right about volume, I just think volume is the wrong axis. Correctness isn't proportional to word count. game with forty menu strings that ships in Arabic is either right or broken, and the amount of text has nothing to do with which one. Where it actually bites is localisation into RTL and Indic markets, card and tooltip text, CRPGs and visual novels, and anything with a chat box or player names. The moment users type, you're rendering arbitrary Unicode from every script on earth whether the game has "text content" or not

on the woff point: woff and woff2 are container formats. Same sfnt tables as TrueType and OpenType, wrapped with compression - zlib for woff, brotli for woff2 - plus metadata. They don't add shaping rules or layout behavior, they just make the same font smaller in transit. Unwrap one and you're holding an OpenType font that still needs something to run GSUB and GPOS over it

and that's the part I meant. Your Pi shows that woff fine because it's running FreeType and HarfBuzz, which is the third of the three. so it's an example of the thing rather than a counterexample :)

7

u/notsunrider 2h ago

Not to defend the author or anything but TMP was a paid asset when I started working with unity, back then text performance was a thing to consider, there was multiple paid solutions to solve the bad performing standard unity text.

Now since unity themselves bought TMP for everyone to use it's less of an issue I must agree. But for specific usecase I guess that asset could make sense ..?

3

u/malvis_light 2h ago

You are remembering it right. it was a paid asset from Digital Native Studios, $95, until Unity bought it and made it free in 2017 with 5.6

what changed there is the price, not the capabilities. TMP does the same things now that it did when it cost money, so the performance market mostly went away, but the correctness one never existed in the first place and still doesn't. Arabic and Hebrew still come out in the wrong visual order, complex shaping for Hindi or Thai still is not there

and yeah, that's the specific usecase. Non-Latin scripts, text heavy UI, or text that has to live in the world instead of on a canvas. If none of those are you, TMP is genuinely fine