Suporte

Perguntas Frequentes

Respostas diretas sobre o tamanho do build, fontes, o atlas de glifos e o desempenho em runtime — extraídas de perguntas reais de programadores.

Tamanho do Build e Distribuição

O UniText aumenta o tamanho do meu build? O que é que acaba realmente no build?

Não. O UniText não pré-gera atlas de textura por fonte no seu build. Os glifos são rasterizados em runtime num atlas partilhado (baseado em Texture2DArray), com contagem de referências por glifo e remoção LRU. Apenas os dados da fonte vão no seu build — nunca os atlas. Além disso, a Compressão de Fontes integrada (Zstd, nível 22) reduz os dados da fonte em até ~2.7× para latim/árabe (o CJK é mais modesto, ~1.3×).

Preciso de manter e distribuir os ficheiros .ttf?

Não. O asset UniTextFont incorpora os bytes da fonte dentro de si. A referência à fonte de origem existe apenas no Editor (envolvida em #if UNITY_EDITOR) — simplesmente não existe num build de player, pelo que não é uma dependência de runtime e não será arrastada para um AssetBundle através da resolução de dependências. Pode eliminar o .ttf assim que o asset for criado.

Preciso sequer de importar o .ttf para o meu projeto?

Não. Pode criar um UniTextFont a partir de um .ttf localizado em qualquer sítio do seu disco através da janela de ferramentas do UniText (a caixa de diálogo de ficheiros lê os bytes diretamente). Importar a fonte para o projeto é opcional.

Quanto é que o UniText adiciona, na realidade, a um build vazio?

• WebGL: um build vazio ocupa ≈ 6–10 MB (varia consoante a versão do Unity e os pacotes instalados); o UniText adiciona as suas bibliotecas nativas (HarfBuzz, FreeType). São as mesmas bibliotecas padrão da indústria que o próprio Advanced Text Generator do UI Toolkit do Unity distribui — nada de exótico (o UniText apenas traz as suas próprias cópias). • Android: um APK com duas arquiteturas transporta ambas — cerca de +4 MB por arquitetura. Mas quando publica um AAB, o Google Play entrega um bundle específico do dispositivo, pelo que o utilizador transfere apenas a sua própria arquitetura (~4 MB), e não ambas.

Como é que o UniText se compara ao TextMesh Pro para CJK ou fontes grandes?

Com o TMP no modo Static de povoamento do atlas, pré-gerar o conjunto completo de glifos de uma fonte CJK típica aumenta o build em dezenas a centenas de MB (vários atlas de 4096²/8192²; conte com ~80–250 MB consoante o número de glifos e a resolução). O ponto essencial: o overhead do UniText não escala com o número de glifos — são os mesmos poucos MB, quer distribua latim quer CJK completo.

Posso carregar fontes dinamicamente a partir de um servidor ou CDN?

Sim — isso é da responsabilidade do programador, e o UniText não se intromete. Transfira os bytes da fonte com o seu próprio código (UnityWebRequest) e crie um UniTextFont a partir deles em runtime através de CreateFontAsset(byte[]). Para reduzir uma fonte apenas aos caracteres de que precisa (subsetting), use a ferramenta de build-time do UniText. Não existe um carregador automático de CDN integrado no pacote — isso é deliberadamente da responsabilidade do projeto, e não do motor.

Fontes e Fontes do Sistema

O UniText pode usar a fonte de sistema do SO? Qual é o custo em memória e no arranque?

Sim — o SystemFont lê o ficheiro da fonte diretamente do SO em runtime, pelo que não tem qualquer efeito no tamanho do build (nada é pré-gerado). A resolução é diferida (ocorre na primeira utilização), por isso não atrasa o arranque da aplicação.

O WebGL suporta fontes de sistema?

Não — e essa é uma limitação do navegador, não do UniText. A sandbox do navegador não expõe as fontes do SO. Para WebGL, incorpore uma fonte num asset UniTextFont (ou carregue os bytes por si próprio — veja a pergunta sobre CDN acima).

Atlas de Glifos — SDF Detail e Tile Size

O que fazem, afinal, o “SDF Detail” e o “Tile Size Offset”?

Os glifos vivem em tiles de três tamanhos — 64, 128, 256 — e o tamanho é escolhido a partir da complexidade do contorno (muitos segmentos → 128/256, um contorno simples → 64). • O SDF Detail é um multiplicador da estimativa de complexidade. Aumente-o e um glifo já não trivial tem mais probabilidade de subir para um tile maior. (Uma forma genuinamente simples mantém-se em 64 — o multiplicador só afeta os glifos acima do limiar.) • O Tile Size Offset é um passo fixo ao longo da escala de tamanhos (64 escolhido + offset 1 → 128; intervalo −2..+2).

Qual dos dois devo priorizar para o desempenho?

Nenhum isoladamente — ambos apenas decidem o tamanho final do tile, e o custo é determinado unicamente por esse tamanho. Duas combinações que resultem no mesmo tamanho de tile custam exatamente o mesmo. Procure o menor tamanho de tile que ainda ofereça qualidade aceitável.

Desempenho em Runtime

Quando é que o UniText rasteriza os glifos? Copia memória a cada frame?

Apenas quando um glifo ainda não está no atlas — nunca a cada frame. Para “Hello world”, rasteriza os glifos únicos H e l o w r d. Um segundo H não faz nada; um a rasteriza apenas o a.

Porque é que há um breve engasgo quando muito texto novo aparece de uma só vez?

O custo é proporcional ao número de glifos únicos, vistos pela primeira vez, rasterizados nesse frame — e não ao comprimento do texto. No nosso benchmark, ~2000 glifos únicos no primeiro frame demoram ≈ 1 segundo num dispositivo Android típico; o TMP e o UI Toolkit levam 10+ segundos no mesmo cenário. Reutilizar glifos em cache é gratuito.

Não vejo nenhum job do UniText no Profiler — a multithreading está mesmo a funcionar?

O UniText mal depende do Unity Job System no caminho crítico (hot path) — por design. A rasterização de glifos (o nosso lpSDF / lpMSDF proprietário) corre na GPU através de um compute shader por predefinição; os jobs de Burst são apenas o fallback para CPU quando o compute não está disponível. A multithreading principal — shaping, layout, geração de mesh — corre no pool de threads do SO do próprio UniText (não nos Unity Jobs, razão pela qual não aparecem no profiler de Jobs). Por isso, “nenhum job do UniText” não significa “as threads estão desligadas”: ou o trabalho foi para a GPU, ou o atlas já está quente, ou o texto está abaixo do limiar de paralelismo (labels curtas ou únicas são processadas sequencialmente — é mais barato assim).

O MonoBehaviour.Update() prejudica o desempenho? É preciso um único UniTextManager?

“O Update() é lento” é um mito para builds de release. O overhead da chamada do método mágico a partir de código nativo é real, mas negligenciável (~1000 chamadas ≈ 0.16 ms) — não é o gargalo. O custo real em código ingénuo é o layout de memória AoS, não o callback em si; o UniText aplica SoA onde isso importa (atributos Unicode, métricas, buffers por pixel). (É também por isso que o ECS é rápido — por causa do SoA, e não de “magia do ECS”.) E, de qualquer forma, o UniText é centralizado — só que não como um gestor MonoBehaviour: o próprio Update() está praticamente vazio, e o trabalho pesado é reunido num único passo em lote nos callbacks de render do Canvas (o que também proporciona o paralelismo entre componentes).

Não encontrou a sua resposta?

Pergunte no nosso Discord — perguntas como estas foram exatamente o que moldou esta página, e costumamos responder depressa.