Des réponses directes sur la taille du build, les polices, l'atlas de glyphes et les performances à l'exécution — distillées à partir de vraies questions de développeurs.
Non. UniText ne pré-génère pas d'atlas de texture par police dans votre build. Les glyphes sont rastérisés à l'exécution dans un atlas partagé (basé sur Texture2DArray), avec comptage de références par glyphe et éviction LRU. Seules les données de police sont livrées dans votre build — jamais les atlas. En plus de cela, la compression de polices intégrée (Zstd, niveau 22) réduit les données de police jusqu'à ~2.7× pour le latin/arabe (le CJK est plus modeste, ~1.3×).
Non. L'asset UniTextFont intègre les octets de la police en son sein. La référence à la police source existe uniquement dans l'éditeur (encadrée par #if UNITY_EDITOR) — elle n'existe tout simplement pas dans un build joueur, ce n'est donc pas une dépendance à l'exécution et elle ne sera pas tirée dans un AssetBundle via la résolution des dépendances. Vous pouvez supprimer le .ttf une fois l'asset créé.
Non. Vous pouvez construire un UniTextFont à partir d'un .ttf situé n'importe où sur votre disque via la fenêtre d'outils UniText (la boîte de dialogue de fichier lit les octets directement). Importer la police dans le projet est facultatif.
• WebGL : un build vide fait ≈ 6–10 MB (cela varie selon la version d'Unity et les packages installés) ; UniText ajoute ses bibliothèques natives (HarfBuzz, FreeType). Ce sont les mêmes bibliothèques standard de l'industrie que celles livrées par l'Advanced Text Generator du UI Toolkit d'Unity — rien d'exotique (UniText embarque simplement ses propres copies). • Android : un APK avec deux architectures les embarque toutes les deux — environ +4 MB par architecture. Mais lorsque vous publiez un AAB, Google Play livre un bundle spécifique à l'appareil, si bien que l'utilisateur ne télécharge que sa propre architecture (~4 MB), et non les deux.
Avec TMP en mode Static (population de l'atlas), la pré-génération du jeu complet de glyphes d'une police CJK typique alourdit le build de dizaines à centaines de MB (plusieurs atlas 4096²/8192² ; comptez ~80–250 MB selon le nombre de glyphes et la résolution). Le point clé : la surcharge d'UniText n'augmente pas avec le nombre de glyphes — ce sont les mêmes quelques MB que vous livriez du latin ou du CJK complet.
Oui — cela relève du côté du développeur, et UniText ne s'y oppose pas. Téléchargez les octets de la police avec votre propre code (UnityWebRequest) et construisez-en un UniTextFont à l'exécution via CreateFontAsset(byte[]). Pour réduire une police aux seuls caractères dont vous avez besoin (subsetting), utilisez l'outil d'UniText disponible au moment du build. Il n'y a pas d'auto-chargeur CDN intégré dans le package — c'est délibérément la responsabilité du projet, pas celle du moteur.
Oui — SystemFont lit le fichier de police directement depuis l'OS à l'exécution, sans donc aucun effet sur la taille du build (rien n'est pré-généré). La résolution est paresseuse (à la première utilisation), elle ne ralentit donc pas le démarrage de l'application.
Non — et c'est une limitation du navigateur, pas d'UniText. Le bac à sable du navigateur n'expose pas les polices de l'OS. Pour le WebGL, intégrez une police dans un asset UniTextFont (ou chargez les octets vous-même — voir la question sur le CDN ci-dessus).
Les glyphes résident dans des tuiles de trois tailles — 64, 128, 256 — et la taille est choisie selon la complexité du contour (beaucoup de segments → 128/256, un contour simple → 64). • SDF Detail est un multiplicateur appliqué à l'estimation de complexité. Augmentez-le et un glyphe déjà non trivial a plus de chances de passer à une tuile plus grande. (Une forme réellement simple reste à 64 — le multiplicateur n'affecte que les glyphes au-dessus du seuil.) • Tile Size Offset est un décalage ferme le long de l'échelle des tailles (choix 64 + décalage 1 → 128 ; plage −2..+2).
Aucun des deux isolément — les deux ne font que déterminer la taille finale de la tuile, et le coût est fixé par cette seule taille. Deux combinaisons qui aboutissent à la même taille de tuile coûtent exactement la même chose. Visez la plus petite taille de tuile qui offre encore une qualité acceptable.
Uniquement lorsqu'un glyphe n'est pas déjà dans l'atlas — jamais à chaque frame. Pour « Hello world », il rastérise les glyphes uniques H e l o w r d. Un second H ne fait rien ; un a ne rastérise que le a.
Le coût est proportionnel au nombre de glyphes uniques, vus pour la première fois, rastérisés durant cette frame — pas à la longueur du texte. Dans notre benchmark, ~2000 glyphes uniques sur la première frame représentent ≈ 1 seconde sur un appareil Android typique ; TMP et UI Toolkit prennent 10+ secondes dans le même scénario. Réutiliser les glyphes en cache est gratuit.
UniText ne s'appuie quasiment pas sur le Job System d'Unity sur le chemin critique — c'est voulu. La rastérisation des glyphes (notre lpSDF / lpMSDF propriétaire) s'exécute par défaut sur le GPU via un compute shader ; les jobs Burst ne sont que la solution de repli CPU lorsque le compute n'est pas disponible. Le multithreading principal — shaping, mise en page, génération de mesh — s'exécute sur le propre pool de threads OS d'UniText (pas les Unity Jobs, d'où le fait qu'ils n'apparaissent pas dans le profileur Jobs). Ainsi, « aucun job UniText » ne signifie pas « les threads sont désactivés » : soit le travail est parti sur le GPU, soit l'atlas est déjà chaud, soit le texte est en dessous du seuil de parallélisme (les libellés courts ou uniques sont traités séquentiellement — c'est moins coûteux ainsi).
« Update() est lent » est un mythe pour les builds de release. La surcharge de l'appel de la méthode magique depuis le code natif est réelle mais négligeable (~1000 appels ≈ 0.16 ms) — ce n'est pas le goulot d'étranglement. Le vrai coût dans du code naïf est la disposition mémoire AoS, pas le callback lui-même ; UniText applique le SoA là où cela compte (attributs Unicode, métriques, buffers par pixel). (C'est aussi pourquoi ECS est rapide — grâce au SoA, pas à une « magie ECS ».) Et UniText est de toute façon centralisé — simplement pas sous la forme d'un manager MonoBehaviour : Update() lui-même est quasiment vide, et le gros du travail est regroupé en une seule passe groupée sur les callbacks de rendu du Canvas (ce qui procure également le parallélisme inter-composants).
Posez votre question sur notre Discord — ce sont exactement des questions comme celles-ci qui ont façonné cette page, et nous répondons généralement vite.