Wsparcie

Najczęściej zadawane pytania

Konkretne odpowiedzi na temat rozmiaru buildu, czcionek, atlasu glifów i wydajności w runtime — wydestylowane z prawdziwych pytań deweloperów.

Rozmiar buildu i dystrybucja

Czy UniText rozdmuchuje rozmiar mojego buildu? Co właściwie trafia do buildu?

Nie. UniText nie zapieka atlasów tekstur poszczególnych czcionek do Twojego buildu. Glify są rasteryzowane w runtime do współdzielonego atlasu (opartego na Texture2DArray) ze zliczaniem referencji per glif i eksmisją LRU. Do buildu trafiają wyłącznie dane czcionki — nigdy atlasy. Dodatkowo wbudowana kompresja czcionek (Zstd, poziom 22) zmniejsza dane czcionki nawet ~2.7× dla łaciny/arabskiego (CJK skromniej, ~1.3×).

Czy muszę przechowywać i dostarczać pliki .ttf?

Nie. Asset UniTextFont osadza bajty czcionki w sobie. Odwołanie do źródłowej czcionki istnieje tylko w Edytorze (opakowane w #if UNITY_EDITOR) — po prostu nie istnieje w buildzie gracza, więc nie jest zależnością w runtime i nie zostanie wciągnięte do AssetBundle przez wyszukiwanie zależności. Plik .ttf możesz usunąć, gdy asset zostanie utworzony.

Czy w ogóle muszę importować .ttf do swojego projektu?

Nie. Możesz zbudować UniTextFont z pliku .ttf znajdującego się w dowolnym miejscu na dysku, korzystając z okna narzędzia UniText (okno wyboru pliku czyta bajty bezpośrednio). Zaimportowanie czcionki do projektu jest opcjonalne.

Ile UniText faktycznie dodaje do pustego buildu?

• WebGL: pusty build waży ≈ 6–10 MB (zależnie od wersji Unity i zainstalowanych paczek); UniText dodaje swoje natywne biblioteki (HarfBuzz, FreeType). To te same standardowe w branży biblioteki, które dostarcza sam Advanced Text Generator z UI Toolkit Unity — nic egzotycznego (UniText po prostu nosi własne kopie). • Android: APK z dwiema architekturami niesie obie — około +4 MB na architekturę. Ale gdy publikujesz AAB, Google Play dostarcza bundle dopasowany do urządzenia, więc użytkownik pobiera tylko swoją architekturę (~4 MB), a nie obie.

Jak UniText wypada w porównaniu z TextMesh Pro przy CJK lub dużych czcionkach?

Przy TMP w trybie zapełniania atlasu Static zapieczenie pełnego zestawu glifów typowej czcionki CJK rozdmuchuje build o dziesiątki do setek MB (kilka atlasów 4096²/8192²; spodziewaj się ~80–250 MB w zależności od liczby glifów i rozdzielczości). Kluczowa rzecz: narzut UniText nie skaluje się z liczbą glifów — to te same kilka MB, niezależnie od tego, czy dostarczasz łacinę, czy pełne CJK.

Czy mogę ładować czcionki dynamicznie z serwera lub CDN?

Tak — to leży po stronie dewelopera, a UniText nie staje na przeszkodzie. Pobierz bajty czcionki własnym kodem (UnityWebRequest) i zbuduj z nich UniTextFont w runtime przez CreateFontAsset(byte[]). Aby okroić czcionkę do samych potrzebnych znaków (subsetting), użyj narzędzia UniText działającego na etapie budowania. W paczce nie ma wbudowanego auto-ładowacza CDN — to celowo odpowiedzialność projektu, nie silnika.

Czcionki i czcionki systemowe

Czy UniText może używać czcionki systemowej OS? Ile to kosztuje w pamięci i przy starcie?

Tak — SystemFont czyta plik czcionki bezpośrednio z systemu operacyjnego w runtime, więc nie ma wpływu na rozmiar buildu (nic nie jest zapiekane). Rozwiązywanie odbywa się leniwie (przy pierwszym użyciu), więc nie spowalnia startu aplikacji.

Czy WebGL obsługuje czcionki systemowe?

Nie — i to ograniczenie przeglądarki, nie UniText. Piaskownica przeglądarki nie udostępnia czcionek systemu operacyjnego. W przypadku WebGL osadź czcionkę w asset UniTextFont (albo załaduj bajty samodzielnie — zobacz pytanie o CDN powyżej).

Atlas glifów — SDF Detail i Tile Size

Co właściwie robią „SDF Detail” i „Tile Size Offset”?

Glify mieszczą się w kafelkach trzech rozmiarów — 64, 128, 256 — a rozmiar dobierany jest na podstawie złożoności konturu (wiele segmentów → 128/256, prosty kontur → 64). • SDF Detail to mnożnik szacowanej złożoności. Podnieś go, a i tak już nietrywialny glif z większym prawdopodobieństwem przeskoczy do większego kafelka. (Naprawdę prosty kształt zostaje przy 64 — mnożnik wpływa tylko na glify powyżej progu.) • Tile Size Offset to twardy krok po drabinie rozmiarów (wybrany 64 + offset 1 → 128; zakres −2..+2).

Który z tych dwóch powinienem traktować priorytetowo pod kątem wydajności?

Żaden w oderwaniu — oba jedynie decydują o końcowym rozmiarze kafelka, a koszt wyznacza wyłącznie ten rozmiar. Dwie kombinacje, które sprowadzają się do tego samego rozmiaru kafelka, kosztują dokładnie tyle samo. Celuj w najmniejszy rozmiar kafelka, który wciąż daje akceptowalną jakość.

Wydajność w runtime

Kiedy UniText rasteryzuje glify? Czy kopiuje pamięć w każdej klatce?

Tylko wtedy, gdy glifu nie ma jeszcze w atlasie — nigdy co klatkę. Dla „Hello world” rasteryzuje unikalne glify H e l o w r d. Drugie H nie robi nic; litera a rasteryzuje tylko samo a.

Skąd bierze się krótkie zacięcie, gdy naraz pojawia się dużo nowego tekstu?

Koszt jest proporcjonalny do liczby unikalnych, widzianych po raz pierwszy glifów rasteryzowanych w danej klatce — a nie do długości tekstu. W naszym benchmarku ~2000 unikalnych glifów w pierwszej klatce to ≈ 1 sekunda na typowym urządzeniu z Android; TMP i UI Toolkit potrzebują w tym samym scenariuszu 10+ sekund. Ponowne użycie glifów z cache’u jest darmowe.

Nie widzę zadania UniText w Profilerze — czy wielowątkowość faktycznie działa?

UniText niemal nie polega na Unity Job System na gorącej ścieżce — to celowe. Rasteryzacja glifów (nasze autorskie lpSDF / lpMSDF) domyślnie działa na GPU przez compute shader; zadania Burst są tylko awaryjnym rozwiązaniem na CPU, gdy compute jest niedostępny. Główna wielowątkowość — shaping, layout, generowanie meshu — działa na własnej puli wątków OS UniText (nie na Unity Jobs, dlatego nie pojawiają się w profilerze Jobs). Zatem „brak zadania UniText” nie oznacza „wątki są wyłączone”: albo praca trafiła na GPU, albo atlas jest już rozgrzany, albo tekst jest poniżej progu równoległości (krótkie lub pojedyncze etykiety przetwarzane są sekwencyjnie — tak jest taniej).

Czy MonoBehaviour.Update() szkodzi wydajności? Czy potrzebny jest jeden UniTextManager?

„Update() jest wolny” to mit w przypadku buildów release. Narzut wywołania magicznej metody z kodu natywnego jest realny, ale pomijalny (~1000 wywołań ≈ 0.16 ms) — to nie jest wąskie gardło. Prawdziwym kosztem w naiwnym kodzie jest układ pamięci AoS, a nie samo wywołanie zwrotne; UniText stosuje SoA tam, gdzie ma to znaczenie (atrybuty Unicode, metryki, bufory per piksel). (To także powód, dla którego ECS jest szybki — dzięki SoA, a nie „magii ECS”.) A UniText i tak jest scentralizowany — po prostu nie jako menedżer MonoBehaviour: samo Update() jest niemal puste, a ciężka praca jest zbierana w jeden wsadowy przebieg na wywołaniach zwrotnych renderowania Canvas (co daje też równoległość między komponentami).

Nie znalazłeś odpowiedzi?

Zapytaj na naszym Discordzie — to właśnie takie pytania ukształtowały tę stronę, a zwykle odpowiadamy szybko.