Skip to content

Repository files navigation

Inky, the Unity DirectTMP mascot

🖋️ Unity DirectTMP

Point TextMeshPro at a .ttf. That's the whole tool.
فایل فونت رو مستقیم بده به TextMeshPro — همین.
TextMeshPro に .ttf を渡すだけ。それだけです。

Englishفارسی日本語

license unity version textmeshpro shaping price

🌐 Plugin page🌐 صفحهٔ افزونه🌐 プラグインページ


🇬🇧 English

No Font Asset Creator. No character set. No □□□. Drop a font file on a label and it is drawn from that file — every glyph, every script, rasterized the moment it is first needed.

And Persian, Arabic and Urdu come out joined and in reading order, using the font's own OpenType tables — so modern faces like Vazirmatn, Sahel, Shabnam, IRANSans and Noto Sans Arabic work exactly as they were designed to.

📦 Install

Package Manager ▸ +Add package from git URL…

https://github.com/AmirCollider/UnityDirectTMP.git

🚀 Use it

  1. Select your TextMeshPro label.
  2. Add Component ▸ Unity DirectTMP ▸ Direct Font
  3. Drop a .ttf or .otf into Font.

That's it. One component, one label, one font — nothing is applied project-wide, and two labels with two different fonts never interfere.

💡 Have a whole UI to convert? Select the Canvas and use Unity DirectTMP ▸ Add Direct Font to Selection — it does every label underneath it.

From code, if you prefer:

DirectTMP.Apply(label, myFont);              // same thing the component does
DirectTMP.Outline(label, 0.2f, Color.black); // an outline on this label only
label.font = DirectTMP.Load(myFont);         // just the font asset
label.font = DirectTMP.LoadFromFile(path);   // a .ttf on disk, at runtime

🎛️ The fields

Field What it does
Font The font file. The only one you actually need.
Persian / Arabic Used when the text is mostly Persian, Arabic or Urdu. Empty = use Font.
日本語 / 中文 / 한국어 Used when the text is mostly Japanese, Chinese or Korean. Empty = use Font.
English / Latin Used when the text is mostly English or another Latin language. Empty = use Font.
Outline ▸ Width How thick an outline is drawn around this label's letters. 0 is no outline.
Outline ▸ Colour The colour of that outline.
Own material Gives this label its own material, so anything set on it stays its own.
Join Persian / Arabic Letter joining and right-to-left reading order. Free for text with no Arabic script.
Fix wrapped lines Keeps wrapped right-to-left lines in the correct order.

✨ Why people keep it

  • 🌏 A font per language, on one label. Fill in the language fields you have fonts for. Each time the text changes, the script it is actually in is detected and the matching font is used — by counting characters, so "Unity ۱۲۳ سلام دنیا" is Persian, not English.
  • 🎨 An outline that belongs to one label. In TextMeshPro every label sharing a font shares one material, so an outline on one is an outline on all. Set Outline ▸ Width here instead: it goes on a material this label owns, and it is kept on the component — so it survives a recompile, play mode and the build, which an outline set on a generated material cannot.
  • 🩺 Persian that actually reads. Joined shapes are read from the font's own GSUB table and verified glyph-for-glyph against HarfBuzz — the engine behind Chrome, Firefox, Android and macOS — across five fonts.
  • 🧩 Everything else, free. Japanese, Chinese, Korean, Cyrillic, Greek, Thai, emoji and symbols: nothing to configure. If the font has the glyph, you get it.
  • 🤝 Polite. Rich-text tags are never shaped or reordered, and label.text is never written to.
Under the hood, and the honest limits

Shaping used to emit Unicode presentation forms (U+FE70..FEFF, U+FB50..FBFF) and ask the font whether it had them. Fonts built before OpenType do; modern Persian faces do not — they carry the plain letters and express joining in GSUB. So the font said no and the word stayed unjoined. Unity DirectTMP now reads the font's own GSUB, asks which glyph it would use for each letter in each position, and registers that glyph in the font asset.

A letter's joining class is also treated as a fact about Unicode, not about the font — so one missing glyph can no longer change the shape of the letter next to it — and letters Unicode never gave a presentation codepoint to (most of Arabic Extended-A, much of Kurdish, Sindhi and the African orthographies) join too.

The font asset is built at load and has no file behind it, and so does the material that comes with it. That is what makes the Font Asset Creator unnecessary, and it is also why the outline is a field on the component: a material that cannot be saved cannot remember an outline you set on it, and every reload — a recompile, play mode, reopening the scene — hands the label a fresh one. Anything else you set on a material by hand has the same lifetime, so set it from code after the label is up, or ask for a field for it.

What it does not do: contextual alternates (you get the standard joined shape, not Nastaliq typesetting), mark positioning (GPOS — harakat sit at the font's default advance), and a rich-text tag placed mid-sentence inside a right-to-left line splits it into two correctly-ordered runs laid out left-to-right relative to each other. A tag around a whole phrase is fine.

🧰 Requirements

Unity 2021.3+ and TextMeshPro (bundled with Unity). Nothing else.

If a font produces nothing, the component's Inspector names the reason — usually TMP Essential Resources not imported, Include Font Data off on the font importer, its Character mode not set to Dynamic, or a missing distance-field shader.

🔗 Links

Plugin pageamircollider.comChangelog

↑ back to top


🇮🇷 فارسی

بدون Font Asset Creator، بدون انتخاب کاراکتر، بدون □□□. فایل فونت را روی لیبل بگذارید و همان لیبل مستقیماً از همان فایل کشیده می‌شود — هر گلیف، هر خط، درست همان لحظه‌ای که لازم شود.

و فارسی، عربی و اردو چسبیده و با ترتیب درست در می‌آیند، آن هم با استفاده از جدول‌های OpenType خودِ فونت — پس وزیرمتن، ساحل، شبنم، ایران‌سنس و نوتو دقیقاً همان‌طور کار می‌کنند که طراحی شده‌اند.

📦 نصب

Package Manager ‏▸ + ‏▸ Add package from git URL…

https://github.com/AmirCollider/UnityDirectTMP.git

🚀 استفاده

۱. لیبل TextMeshPro خود را انتخاب کنید. ۲. Add Component ▸ Unity DirectTMP ▸ Direct Font ۳. یک .ttf یا .otf داخل فیلد Font بیندازید.

تمام. یک کامپوننت، یک لیبل، یک فونت — هیچ چیزی روی کل پروژه اعمال نمی‌شود و دو لیبل با دو فونت مختلف هیچ کاری به هم ندارند.

💡 یک UI کامل دارید؟ Canvas را انتخاب کنید و Unity DirectTMP ▸ Add Direct Font to Selection را بزنید — همهٔ لیبل‌های زیرش را انجام می‌دهد.

اگر کد را ترجیح می‌دهید:

DirectTMP.Apply(label, myFont);              // همان کاری که کامپوننت می‌کند
DirectTMP.Outline(label, 0.2f, Color.black); // OutLine فقط روی همین لیبل
label.font = DirectTMP.Load(myFont);         // فقط خودِ فونت‌اَسِت
label.font = DirectTMP.LoadFromFile(path);   // یک .ttf روی دیسک، در زمان اجرا

🎛️ فیلدها

فیلد کارش چیست
Font فایل فونت. تنها فیلدی که واقعاً لازم دارید.
Persian / Arabic وقتی متن بیشتر فارسی، عربی یا اردو باشد. خالی = همان Font.
日本語 / 中文 / 한국어 وقتی متن بیشتر ژاپنی، چینی یا کره‌ای باشد. خالی = همان Font.
English / Latin وقتی متن بیشتر انگلیسی یا لاتین باشد. خالی = همان Font.
Outline ▸ Width ضخامت OutLine دور حروف همین لیبل. صفر یعنی بدون OutLine.
Outline ▸ Colour رنگ همان OutLine.
Own material متریال مخصوص همین لیبل، تا هرچه رویش تنظیم شود مال خودش بماند.
Join Persian / Arabic چسبیدن حروف و ترتیب راست‌به‌چپ. برای متن بدون خط عربی هیچ هزینه‌ای ندارد.
Fix wrapped lines ترتیب درست خط‌های شکسته‌شده در متن راست‌به‌چپ.

✨ چرا نگهش می‌دارند

  • 🌏 یک فونت برای هر زبان، روی یک لیبل. فیلد زبان‌هایی را که فونت دارید پر کنید. هر بار متن عوض شود، تشخیص داده می‌شود متن واقعاً در چه خطی نوشته شده و فونت مربوطه استفاده می‌شود — با شمردن کاراکترها، پس "Unity ۱۲۳ سلام دنیا" فارسی حساب می‌شود، نه انگلیسی.
  • 🎨 OutLine ای که فقط مال یک لیبل است. در TextMeshPro همهٔ لیبل‌هایی که یک فونت دارند یک متریال مشترک دارند، پس OutLine روی یکی یعنی OutLine روی همه. به جایش Outline ▸ Width را همین‌جا تنظیم کنید: روی متریالی می‌نشیند که مال خودِ همین لیبل است و مقدارش روی خودِ کامپوننت ذخیره می‌شود — پس بعد از کامپایل دوباره، ورود به Play Mode و در بیلد هم سرِ جایش می‌ماند؛ کاری که OutLine تنظیم‌شده روی یک متریالِ ساخته‌شده در زمان اجرا نمی‌تواند بکند.
  • 🩺 فارسیِ واقعاً خوانا. شکل‌های چسبیده از جدول GSUB خودِ فونت خوانده می‌شود و خروجی گلیف‌به‌گلیف با HarfBuzz — موتور پشت کروم، فایرفاکس، اندروید و مک‌اواس — روی پنج فونت تست شده است.
  • 🧩 بقیه‌اش مجانی. ژاپنی، چینی، کره‌ای، سیریلیک، یونانی، تایلندی، ایموجی و نمادها: هیچ تنظیمی ندارند. اگر فونت گلیف را داشته باشد، شما هم دارید.
  • 🤝 مؤدب. تگ‌های Rich Text هرگز شکل‌دهی یا جابه‌جا نمی‌شوند و چیزی در label.text نوشته نمی‌شود.
پشت صحنه، و محدودیت‌های صادقانه

قبلاً شکل‌دهی حروف را به فرم‌های نمایشی یونیکد (U+FE70..FEFF و U+FB50..FBFF) تبدیل می‌کرد و بعد از فونت می‌پرسید آن‌ها را دارد یا نه. فونت‌های قبل از OpenType دارند؛ فونت‌های مدرن فارسی ندارند — آن‌ها حروف ساده را نگه می‌دارند و قواعد چسبیدن را در GSUB می‌گذارند. پس جواب «نه» می‌شد و کل کلمه بدون جوین می‌ماند. حالا GSUB خودِ فونت خوانده می‌شود و همان گلیفی که خودِ فونت می‌کشد در Font Asset ثبت می‌شود.

همچنین کلاسِ اتصال هر حرف یک واقعیت دربارهٔ یونیکد در نظر گرفته می‌شود نه دربارهٔ فونت — پس یک گلیف غایب دیگر نمی‌تواند شکل حرفِ کنارش را خراب کند — و حروفی که یونیکد اصلاً برایشان فرم نمایشی تعریف نکرده (بیشتر Arabic Extended-A و بخش زیادی از کردی، سندی و خط‌های آفریقایی) هم می‌چسبند.

آنچه انجام نمی‌دهد: جایگزین‌های زمینه‌ای (شکل چسبیدهٔ استاندارد را می‌گیرید، نه حروف‌چینی نستعلیق)، جای‌گذاری علامت‌ها (GPOS — حرکات سر جای پیش‌فرض فونت می‌نشینند)، و یک تگ Rich Text در وسط یک جملهٔ راست‌به‌چپ آن را به دو بخش تقسیم می‌کند که هرکدام ترتیب درستی دارند ولی نسبت به هم چپ‌به‌راست چیده می‌شوند. تگ دور کل یک عبارت هیچ مشکلی ندارد.

🧰 پیش‌نیازها

یونیتی 2021.3 به بالا و TextMeshPro (همراه خود یونیتی). همین.

اگر فونتی چیزی نشان نداد، خودِ Inspector کامپوننت دلیلش را می‌گوید — معمولاً وارد نشدن TMP Essential Resources، خاموش بودن Include Font Data در ایمپورتر فونت، Dynamic نبودن حالت Character آن، یا نبودن شیدر distance-field.

🔗 لینک‌ها

صفحهٔ افزونهamircollider.comتغییرات نسخه‌ها

↑ برگشت به بالا


🇯🇵 日本語

Font Asset Creator も、文字セットの指定も、□□□ も、もうありません。 ラベルにフォントファイルを渡せば、そのラベルはそのファイルから描画されます。 グリフは最初に必要になった瞬間にラスタライズされるので、事前準備はゼロです。

さらにペルシャ語・アラビア語・ウルドゥー語は、フォント自身の OpenType テーブルを 使って正しく連結され、正しい語順で表示されます。

📦 インストール

Package Manager ▸ +Add package from git URL…

https://github.com/AmirCollider/UnityDirectTMP.git

🚀 使い方

  1. TextMeshPro のラベルを選択します。
  2. Add Component ▸ Unity DirectTMP ▸ Direct Font
  3. Font.ttf または .otf をドラッグします。

以上です。1 コンポーネント・1 ラベル・1 フォント。プロジェクト全体には何も適用 されず、別々のフォントを使う 2 つのラベルが干渉することもありません。

💡 UI 全体をまとめて変えたいときは、Canvas を選んで Unity DirectTMP ▸ Add Direct Font to Selection を実行してください。配下のラベルすべてに適用されます。

コードから使う場合:

DirectTMP.Apply(label, myFont);              // コンポーネントと同じ処理
DirectTMP.Outline(label, 0.2f, Color.black); // このラベルだけにアウトライン
label.font = DirectTMP.Load(myFont);         // フォントアセットだけ取得
label.font = DirectTMP.LoadFromFile(path);   // ランタイムに .ttf を直接読み込む

🎛️ 各項目

項目 内容
Font フォントファイル。実質これだけで動きます。
Persian / Arabic テキストが主にペルシャ語・アラビア語・ウルドゥー語のとき使用。空欄なら Font
日本語 / 中文 / 한국어 テキストが主に日本語・中国語・韓国語のとき使用。空欄なら Font
English / Latin テキストが主に英語などラテン文字のとき使用。空欄なら Font
Outline ▸ Width このラベルの文字に描くアウトラインの太さ。0 でアウトラインなし。
Outline ▸ Colour そのアウトラインの色。
Own material このラベル専用のマテリアルを与え、設定を他へ波及させません。
Join Persian / Arabic 文字の連結と右から左への語順。アラビア文字を含まないテキストでは無コストです。
Fix wrapped lines 折り返された右から左のテキストの行順を正しく保ちます。

✨ 選ばれている理由

  • 🌏 1 つのラベルに、言語ごとのフォント。 手持ちのフォントを言語欄に入れて おくだけ。テキストが変わるたびに実際の文字体系が判定され、対応するフォントが 使われます。判定は文字数で行うので "Unity ۱۲۳ سلام دنیا" は英語ではなく ペルシャ語として扱われます。
  • 🎨 そのラベルだけのアウトライン。 TextMeshPro では同じフォントを使う ラベルが1 つのマテリアルを共有するため、片方のアウトラインが全部に及びます。 代わりに Outline ▸ Width をここで設定してください。このラベル専用の マテリアルに書き込まれ、値はコンポーネント側に保存されるので、再コンパイル、 Play Mode、ビルドを越えて残ります — 生成されたマテリアルに直接設定した アウトラインにはできないことです。
  • 🩺 本当に読めるペルシャ語。 連結形はフォント自身の GSUB から読み出し、 Chrome・Firefox・Android・macOS を支えるシェーピングエンジン HarfBuzz と グリフ単位で照合して 5 書体で検証済みです。
  • 🧩 それ以外も設定不要。 日本語・中国語・韓国語・キリル文字・ギリシャ文字・ タイ語・絵文字・記号。フォントにグリフがあれば、そのまま出ます。
  • 🤝 行儀がよい。 リッチテキストタグを整形・並べ替えすることはなく、 label.text に書き込むこともありません。
仕組みと、正直な制限

以前のシェーピングは Unicode の表示形U+FE70..FEFFU+FB50..FBFF)を 出力し、フォントがそれを持っているか尋ねていました。OpenType 以前のフォントは 持っていますが、現代のペルシャ語書体は持っていません — 素の文字だけを収録し、 連結規則は GSUB で表現するからです。結果、フォントは「ない」と答え、単語は 連結されないまま残っていました。現在はフォント自身の GSUB を読み、各文字が 各位置でどのグリフになるかを尋ね、そのグリフをフォントアセットに登録します。

また、文字の接続クラスはフォントではなく Unicode の事実として扱われるため、 1 つのグリフの欠落が隣の文字の形を変えてしまうことはもうありません。Unicode が 表示形を与えなかった文字(Arabic Extended-A の大半、クルド語・シンド語・ アフリカ諸言語の正書法の多く)も連結します。

対応していないこと: 文脈依存の異体字(標準的な連結形になります。ナスタリーク 組版ではありません)、マーク配置(GPOS — ハラカートはフォント既定の送り位置に 置かれます)、そして右から左の文中途中に置かれたリッチテキストタグは、各々は 正しい順序を保ちつつ相互には左から右に並ぶ 2 つのランに分割されます。フレーズ 全体を囲むタグなら問題ありません。

🧰 動作環境

Unity 2021.3 以降と TextMeshPro(Unity 同梱)。他の依存関係はありません。

フォントが何も表示しない場合、コンポーネントの Inspector が理由を示します。 多くは TMP Essential Resources 未インポート、フォントインポーターの Include Font Data がオフ、Character モードが Dynamic でない、 distance-field シェーダーが見つからない、のいずれかです。

🔗 リンク

プラグインページamircollider.com変更履歴

↑ トップへ戻る


فارسیEnglish日本語

Made with 🖋️ by AmirCollider · MIT · Changelog

About

Drop a .ttf on a TextMeshPro label and it just works — including joined, right-to-left Persian, Arabic and Urdu, shaped from the font's own OpenType tables. No Font Asset Creator, no character set, no missing-glyph boxes. Free and MIT.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages