支援

常見問題

關於建置大小、字型、字符圖集與執行階段效能的直接解答 — 從真實開發者問題中萃取而來。

建置大小與發行

UniText 會讓我的建置變肥大嗎?實際上會有什麼進入建置?

不會。UniText 不會將各字型的紋理圖集烘焙進您的建置。字符會在執行階段光柵化至一個共用圖集(以 Texture2DArray 為基礎),並具備各字符的參考計數與 LRU 淘汰。只有字型資料會隨您的建置一同發行 — 圖集絕不會。此外,內建的字型壓縮(Zstd,level 22)可將拉丁文/阿拉伯文的字型資料縮減達 ~2.7×(CJK 較為保守,~1.3×)。

我需要保留並隨附 .ttf 檔案嗎?

不需要。UniTextFont 資產會將字型位元組內嵌於自身之中。對來源字型的參考僅存在於 Editor(以 #if UNITY_EDITOR 包裹)— 它在 player 建置中根本不存在,因此並非執行階段相依項,也不會透過相依性查找被拉進 AssetBundle。資產建立完成後,您即可刪除該 .ttf。

我甚至需要將 .ttf 匯入我的專案嗎?

不需要。您可透過 UniText 工具視窗,從磁碟上任何位置的 .ttf 建立 UniTextFont(檔案對話框會直接讀取位元組)。將字型匯入專案為選用。

UniText 實際上會為空白建置增加多少?

• WebGL:空白建置約為 ≈ 6–10 MB(會依 Unity 版本與已安裝的套件而異);UniText 會加入其原生函式庫(HarfBuzz、FreeType)。這些與 Unity 自家 UI Toolkit Advanced Text Generator 所隨附的,是相同的業界標準函式庫 — 並無任何特殊之處(UniText 只是攜帶自己的副本)。 • Android:含兩種架構的 APK 會同時攜帶兩者 — 每種架構約 +4 MB。但當您發行 AAB 時,Google Play 會遞送特定裝置的套件,因此使用者只會下載自己的架構(~4 MB),而非兩者。

在 CJK 或大型字型方面,UniText 與 TextMesh Pro 相比如何?

使用 TMP 的 Static 圖集填充模式時,烘焙典型 CJK 字型的完整字符集會使建置膨脹數十至數百 MB(數個 4096²/8192² 圖集;視字符數量與解析度而定,預期約 ~80–250 MB)。關鍵在於:UniText 的額外開銷不會隨字符數量擴增 — 無論您發行拉丁文或完整 CJK,都是相同的區區數 MB。

我可以從伺服器或 CDN 動態載入字型嗎?

可以 — 那屬於開發者這一端,而 UniText 不會從中作梗。以您自己的程式碼(UnityWebRequest)下載字型位元組,並在執行階段透過 CreateFontAsset(byte[]) 從中建立 UniTextFont。若要將字型精簡至您所需的字元(子集化),請使用 UniText 的建置期工具。套件中並無內建的 CDN 自動載入器 — 這是刻意由專案負責,而非引擎的職責。

字型與系統字型

UniText 能使用作業系統的系統字型嗎?這在記憶體與啟動上有何代價?

可以 — SystemFont 會在執行階段直接從作業系統讀取字型檔案,因此對建置大小毫無影響(不會烘焙任何東西)。解析為惰性(於首次使用時),因此不會拖慢應用程式啟動。

WebGL 支援系統字型嗎?

不支援 — 而這是瀏覽器的限制,並非 UniText 的限制。瀏覽器沙箱不會公開作業系統的字型。對於 WebGL,請將字型內嵌至 UniTextFont 資產(或自行載入位元組 — 請參閱上方的 CDN 問題)。

字符圖集 — SDF Detail 與 Tile Size

「SDF Detail」與「Tile Size Offset」實際上有什麼作用?

字符存放於三種尺寸的圖磚中 — 64、128、256 — 而尺寸取決於輪廓複雜度(區段眾多 → 128/256,簡單輪廓 → 64)。 • SDF Detail 是複雜度估算值的乘數。提高它,原本就已非單純的字符更有可能上移至更大的圖磚。(真正單純的形狀會維持在 64 — 此乘數僅影響超過門檻的字符。) • Tile Size Offset 則是沿尺寸階梯的硬性級距(選定 64 + 偏移 1 → 128;範圍 −2..+2)。

為了效能,這兩者我該優先考量哪一個?

單獨來看兩者皆非 — 兩者都只決定最終的圖磚尺寸,而成本僅由該尺寸所決定。兩種解析至相同圖磚尺寸的組合,成本完全相同。請以仍能提供可接受品質的最小圖磚尺寸為目標。

執行階段效能

UniText 何時會光柵化字符?它會每一幀都複製記憶體嗎?

只有當某個字符尚未存在於圖集中時 — 絕不會每一幀。以「Hello world」為例,它會光柵化不重複的字符 H e l o w r d。第二個 H 不會做任何事;一個 a 就只光柵化該 a。

為何當大量新文字一次出現時,會有短暫的卡頓?

成本與該幀所光柵化的不重複、首次出現字符的數量成正比 — 而非與文字長度成正比。在我們的基準測試中,首幀 ~2000 個不重複字符在典型 Android 裝置上約為 ≈ 1 秒;TMP 與 UI Toolkit 在相同情境下需耗費 10+ 秒。重複使用已快取的字符則不需成本。

我在 Profiler 中看不到 UniText 的 job — 多執行緒真的有在運作嗎?

UniText 在熱路徑上幾乎不依賴 Unity Job System — 這是刻意設計。字符光柵化(我們專有的 lpSDF / lpMSDF)預設透過 compute shader 在 GPU 上執行;Burst job 僅是 compute 無法使用時的 CPU 後備方案。主要的多執行緒 — 塑形、排版、網格生成 — 執行於 UniText 自有的 OS 執行緒池(而非 Unity Jobs,這正是它們不會出現在 Jobs profiler 中的原因)。因此「看不到 UniText job」並不代表「執行緒關閉了」:要麼工作交給了 GPU,要麼圖集已經預熱,要麼文字低於平行化門檻(短標籤或單一標籤會循序處理 — 那樣更省成本)。

MonoBehaviour.Update() 會損害效能嗎?需要單一的 UniTextManager 嗎?

「Update() 很慢」對 release 建置而言是個迷思。從原生程式碼呼叫魔術方法的開銷確實存在,但可忽略不計(~1000 次呼叫 ≈ 0.16 ms)— 它並非瓶頸。天真程式碼中真正的成本是 AoS 記憶體佈局,而非回呼本身;UniText 在關鍵之處(Unicode 屬性、度量、逐像素緩衝區)採用 SoA。(這也是為何 ECS 快速的原因 — 是因為 SoA,而非「ECS 魔法」。)況且 UniText 本就是集中化的 — 只是並非以 MonoBehaviour 管理器的形式:Update() 本身幾乎是空的,而繁重的工作會彙集成單一批次處理,於 Canvas 渲染回呼時執行(這也正是實現跨元件平行化的來源)。

沒找到您要的答案嗎?

來我們的 Discord 提問 — 正是這類問題形塑了此頁面,而我們通常回覆迅速。

有問題嗎?: [email protected]