Você passou um tempo infinito otimizando a interface do usuário do Unity. Mas, para causar inibição, basta uma pequena modificação do pequeno atributo do elemento quase invisível do UI Canvas. E quando isso acontece, mesmo a criação de perfil da interface do usuário do Unity não o impede de diminuir o FPS. Você está pronto para uma longa correção de bug?Foi exatamente o que aconteceu no meu último projeto ...Eu trabalhei duro para otimizar vários painéis de interface do usuário na porta do nosso jogo no
Oculus Quest . Basicamente, a tarefa era reduzir o nível de overdraw para valores aceitáveis, para que a GPU pudesse lidar com o mais importante - renderização em 3D real.
Então, trabalhei na otimização da interface do usuário do Unity por pelo menos um mês e, eventualmente, fiz um progresso muito bom.
Em algum momento, a interface do usuário ficou tão otimizada que quase não afetou os tempos da GPU. As técnicas de escurecimento da interface do usuário opaca que eu implementei compensaram a maioria dos redesenhos causados por camadas da interface do usuário (elementos desenhados em cima de outros elementos).
Então, eu tenho um sistema de interface do usuário híbrido altamente otimizado, que basicamente se sobrepõe aos elementos 3D desenhados sob ele. Tornou-se muito fácil descartar a renderização desses fragmentos sobrepostos.
No entanto, o trabalho ainda estava longe de ser concluído ...Quando conectei o
Unity UI Profiler , uma coisa chamou minha atenção.
Vi que uma CPU sobrecarregada gasta mais de
1 ms em cada quadro na renderização da interface do usuário. É muito tempo para uma plataforma que oferece um orçamento de
13 ms para todo o jogo: física, lógica, renderização 3D, entrada, VR e código de rede.
Afinal, houve casos em que a interface do usuário "matou" o desempenho da CPU ainda mais.
Interface do usuário do Unity: lotes de construção carosE isso diz uma coisa: a
interface do
usuário pode ser otimizada para a GPU, mas isso não significa necessariamente otimização para a CPU .
De fato, ao renderizar a interface do usuário do Unity, as tarefas de CPU e GPU são muito diferentes. Não é de surpreender que recomendo abordar a otimização de CPU e GPU de maneira diferente, e isso foi discutido no meu post anterior sobre
otimização da interface do usuário do Unity .
Os perfis adicionais da interface do usuário do Unity revelaram um problema óbvio: a interface do usuário era constantemente recriada em cada novo quadro, ou seja,
Canvas (Canvas Rebuild) foi reconstruída em cada quadro .
Carga constante na CPU por
1 ms ... oh-oh.
Mas por que a Unity está fazendo isso comigo? Eu pensei que o Unity armazena em cache todas as interfaces do Canvas ...Na verdade sim, é. O Unity efetivamente armazena em cache o Canvas para que eles sejam coletados apenas uma vez.
No entanto, o problema surge quando você altera as propriedades de qualquer um dos elementos da interface do usuário na tela - cor, posição e assim por diante.
Ou seja, todas as animações que amamos, por exemplo, os efeitos dos botões quando você passa o mouse, diminui a produtividade e você provavelmente não sabe disso.
Quando ocorre uma alteração na propriedade da interface do usuário, o Unity executa o famoso Canvas Rebuild, que prejudica o desempenho do jogo .
A reconstrução do Canvas da interface faz com que o mecanismo do Unity atravesse iterativamente todos os elementos da interface do usuário do Canvas para gerar uma lista otimizada de chamadas de desenho (muitos vértices, cores, materiais etc.). E o Canvas Rebuild leva mais tempo do que o
Seat Panda leva para acelerar
de zero a 100 km / h .
Percebendo que estamos constantemente sofrendo com o Canvas Rebuild, seria lógico fazer uma pergunta ...
Por que sofremos com o Canvas Rebuilds e o que pode ser feito sobre isso?Para responder a essa pergunta simples, tive que passar mais de 5 horas estudando o tópico e trabalhando com o
Unity UI Profiler .
Vamos acertar.
1. Profiling Unity UI: está tudo bem, por enquanto ...
Imagine que temos uma interface simples.
Esta interface do usuário não faz nada, apenas aparece na tela e irrita o jogador que tenta ver algo através dela.
Como um conjunto de mais de 350 imagens no Grid Layout Group, fica assim:
Exemplo de criação de perfil da interface de usuário do UnityE tudo está em ordem, apesar das 350 imagens ímpares. No caso padrão, a interface do usuário será renderizada em apenas duas chamadas de empate, porque existem apenas duas imagens exclusivas que não estão no atlas do sprite.
De fato, no criador de perfil, posso ver que praticamente não há carga por parte da CPU.
A maior parte do tempo gasto na interface do usuário é inferior a
0,01 ms , o que é bastante bom.
Perfil da interface do usuário do Unity: um surto misterioso(... na maioria das vezes)Espere, de onde veio esse aumento nos recursos da CPU no final do gráfico?2. Perfil da interface de usuário do Unity: reconstrução repentina da tela!
O que aconteceu no final do perfil da Unity? Muito estranho, em apenas um segundo, a sobrecarga da CPU na interface do usuário do Unity foi mais que o dobro disso.
Eu quero jogar um jogoEncontre as duas diferenças nos exemplos abaixo
(talvez seja necessário abrir as imagens em uma janela separada para ver melhor) .
Criação de perfil de interface de usuário do Unity: tela de baixo custoCriação de perfil de interface de usuário do Unity: reconstrução de telaDou-lhe cinco segundos para descobrir.
5, 4 ... bem, aqui está uma dica para simplificar a tarefa:Criação de perfil de interface de usuário do Unity: reconstrução de tela aéreaUau!PostLateUpdate.UpdateRectTransform
e
UGUI.Rendering.UpdateBatches
desejam fortemente se tornar as principais estrelas deste show.
O que essas áreas fazem?
O primeiro,
UpdateRectTransform
, deixa claro que a transformação de algum objeto mudou e, portanto, o Unity precisa executar uma lógica cara para refletir as mudanças visuais. Não sabemos se foi uma posição, rotação, escala ou alguma outra propriedade do
RectTransform
.
Inferno, nem sabemos se era apenas um atributo, ou todos de uma só vez. Era um único objeto ou vários? E quais?
Esse é o problema: não sabemos .
A segunda peça cara,
UpdateBatches
, está relacionada à necessidade de reconstruir toda a geometria do Canvas. Esse processo é chamado de
Canvas Rebuild . Reconstruir o Canvas significa que o Unity percorre toda a hierarquia do Canvas para gerar uma lista de chamadas de empate. Os vértices, índices, cores e UV de todos os elementos são calculados e, em seguida, é executado um passe de passagem para combinar o número máximo possível de chamadas de empate para reduzir a carga desnecessária na CPU, passando-a para o driver gráfico.
Agora parece que sabemos o que está acontecendo e estamos no caminho certo. Mas como evitar essa revisão do Canvas? O que os causa?
Precisamos de informações mais específicas ...
Resumir- Alterar um atributo em um elemento da interface do usuário marca o próprio elemento como sujo
- O elemento da interface do usuário pode estar completamente sujo, mas também pode ser parcialmente: partes superiores sujas, layout sujo, materiais sujos. É mais fácil recuperar de estados parcialmente sujos
- Quando qualquer elemento do Canvas é marcado como sujo, o Unity o reconstrói completamente
- As reconstruções de tela são caras para a CPU, portanto, a coisa mais importante a ser evitada é
3. Procurando uma praga: uma maneira politicamente incorreta de força bruta
Ainda precisamos responder à seguinte pergunta:
O que causa esses Canvas Rebuild?Acontece que não há
uma maneira
rápida de descobrir, especialmente com uma grande hierarquia do Canvas.
Mas primeiro, mostrarei
um método de força bruta para encontrar o motivo do Canvas Rebuild .
1. Deixe o Unity UI Profiler continuar gravandoFiltraremos as métricas para que possamos focar nos mais importantes: renderização, scripts e interface do usuário.
Acompanhe a marca inicial para entender os custos do esquema atual, que deve incluir o caro Canvas Rebuild.
2. Desative objetos de jogo da interface do usuário e compare as leiturasSelecione o grupo de objetos do jogo e desative-os.
Compare métricas de desempenho.
Se as leituras não tiverem melhorado muito, continue desativando os objetos do jogo até obter uma melhora significativa.
3. Encontre o que muda suas propriedadesConseguimos selecionar o objeto que chama de Canvas Rebuild. Mas o que exatamente se torna a causa deles?
Talvez sua escala mude através do script? Ou a posição dele está mudando pela animação?
Será conveniente clicar com o botão direito do mouse no
RectTransform e selecionar "
Localizar referências na cena "
Quando descobrir o que causa a reconstrução do Canvas, faça algo a respeito, por exemplo, desative animações ou transformações.
Ruben, mas como uso esse método com uma enorme hierarquia de interface do usuário? Não me diga besteiraEu disse que o processo não será rápido nem interessante, mas os jogadores agradecerão a você.
Esse é o ponto. Em primeiro lugar, a existência de uma enorme hierarquia não é uma situação ideal. São hierarquias tão grandes e profundas que tornam o Canvas Rebuild tão caro para a CPU.
Mas hierarquias de interface do usuário grandes e aninhadas podem (e continuarão) surgindo, portanto, espere que o Canvas Rebuild atinja o mais importante: a jogabilidade.
Embora o método da força bruta ajude a encontrar a fonte da revisão do Canvas, ele não escala bem a longo prazo.
Tendo me tornado mais profissional na otimização da interface do usuário, criei uma ferramenta que fornece todas as respostas necessárias para que o projeto atenda às expectativas dos jogadores ...
Reconstrução de tela de criação de perfil4. Bônus: aprimorando os recursos de otimização da interface do usuário do Unity Profiler
Espero que você já entenda o quão frequente e perturbador o Canvas Rebuild pode ser.
Essa perestroika, que infectou meu jogo, levou até 10% de todo o orçamento da CPU!
Como vimos, existe um método de força bruta para encontrar fontes do Canvas Rebuild. Talvez você possa lidar com eles usando as estratégias listadas no meu post sobre como
otimizar a interface do usuário do Unity .
Mas esse processo propenso a erros nunca satisfaria um guru real. Você pode passar vários dias lutando com o Canvas Rebuild, mas no momento mais inesperado eles voltarão a desaparecer assim que você conectar o Unity UI Profiler.
Se você está desenvolvendo um jogo para VR, isso se torna crítico. Não queremos que o Canvas seja reconstruído na interface do usuário do espaço do mundo. Se você não conseguir se livrar da perestroika, seus jogadores provavelmente não a suportarão.
Tudo bem, eu tenho a idéia de me livrar do Canvas Rebuilds. Mas o Unity Profiler quase não fornece informações sobre eles! O que você pode aconselhar?Que bom que você perguntou. Acontece que
podemos convencer o Unity Profiler a fornecer informações úteis sobre o que dificulta o desempenho da interface do usuário .
Podemos estender a funcionalidade do
Unity UI Profiler . Para fazer isso, você precisa modificar o código-fonte da interface do usuário do Unity disponível ao público.
Depois de obter o código-fonte, você precisará
encontrar as funções de código nas quais as reconstruções do Canvas ocorrem . Então precisamos da mágica da API com os
perfis BeginSample e
EndSample .
Se você estiver executando o Unity 2019.1 ou anterior, o código-fonte da UI do Unity está no
repositório do Bitbucket . Há também um guia para baixar, instalar e modificar.
O que eu aconselho? Use uma versão mais recente do Unity, não inferior a 2019.2.0.
As versões mais recentes do Unity são fornecidas por padrão com a interface do usuário de origem , pois o sistema da interface do usuário agora faz parte do gerenciador de pacotes. Esta é a maneira mais fácil de resolver os problemas.
Aqui está uma lista de partes do código que eu descobri durante minha pesquisa, onde posso adicionar chamadas à API de criação de perfil:
Interface do usuário do Unity: fonte de criação de perfilIsso é útil? Sim
Conveniente para o artista / designer? Não.
Foi o poeta que
escreveu a pequena Unity Extension de código aberto que amplia as capacidades do Unity Profiler .
Essa ferramenta gratuita nos permitirá alternar rapidamente entre os diferentes modos de criação de perfil para garantir o desempenho máximo do jogo.
Qual é a melhor coisa sobre esse expansor do Unity Profiler? Funciona fora do editor, aliviando essencialmente toda a dor de cabeça ao criar um perfil da interface do usuário para Android e outras plataformas.
Aqui está, toda a sua energia é controlada por apenas dois botões:
- Buff my Unity Profiler
- Nerf meu perfil de unidade .
Você pode obter essa ferramenta
aqui .