Game teardown

Renderização em escala: Estratégias eficientes para grandes contagens de objetos

MATTHEW WOJTECHKO / MEGA CAT STUDIOSLead Game Developer
Aug 14, 2026
Cena de bairro do jogo Backyard Baseball 2026, da Mega Cat Studios e Playground Productions.
Esta página da Web foi automaticamente traduzida para sua conveniência. Não podemos garantir a precisão ou a confiabilidade do conteúdo traduzido. Se tiver dúvidas sobre a precisão do conteúdo traduzido, consulte a versão oficial em inglês da página da Web.

Este é o quarto post de uma série escrita pela Mega Cat Studios. Neste artigo, Matthew Wojtechko analisa as lições de desempenho aprendidas com o uso de URP e HDRP e explora soluções avançadas, como implementações personalizadas de Grupos de Renderização em Lote para renderização de grama, onde cada milissegundo conta.

Leia as outras postagens deste blog:

Renderizar milhares de objetos sem perda de quadros é um desafio constante. Paisagens urbanas densas e vastas extensões de terra tornaram-se a marca registrada dos jogos modernos. Mas, embora essas paisagens sejam de tirar o fôlego para os jogadores, podem ser uma dor de cabeça para os engenheiros encarregados de manter uma taxa de quadros estável de 60 fps.

E se você estiver mirando em plataformas com menos poder de processamento, como dispositivos móveis ou sem fio, não são apenas esses cenários que representam um problema. Qualquer ambiente que inclua qualquer nível de detalhe pode facilmente causar problemas no hardware.

Há anos que exploramos os limites dos sistemas de renderização da Unity na Mega Cat Studios , e usamos todos os nossos recursos para conseguir reproduzir o estilo artístico cativante de Backyard Baseball em PCs e consoles, sem sacrificar a intenção artística.

Neste post, exploraremos técnicas como agrupamento estático e texturas de animação de vértices, além de compartilhar alguns dos problemas que encontramos em nosso maior título 3D até o momento, tudo com o objetivo de ajudá-lo a manter sua taxa de quadros estável mesmo com o aumento exponencial do número de objetos.

Mesmo um ambiente aparentemente simples pode representar um desafio para renderizar em hardware de baixo custo.
Mesmo um ambiente aparentemente simples pode representar um desafio para renderizar em hardware de baixo custo.

Investigue o que está causando problemas de renderização e, em seguida, otimize.

A renderização é uma colaboração entre a CPU e a GPU.

“A CPU é o treinador e a GPU é o atleta.” "A CPU define as jogadas e a GPU as executa", afirma Liam Dudas, engenheiro de otimização do Backyard Baseball.

Às vezes, o trabalho que a GPU precisa realizar consome mais tempo do que outras tarefas. Malhas, shaders e iluminação complexos podem causar lentidão, e a melhor maneira de melhorar o desempenho é reduzir sua complexidade, pedindo ao artista que otimize esses elementos.

Outras vezes, não é o que a CPU pede para a GPU fazer, mas como ela pede .

A CPU está executando suas instruções de forma otimizada? Será que está demorando muito para descobrir o que desenhar, fazendo com que a CPU fique ociosa em vez de executar o resto do jogo? A CPU está fornecendo informações de forma redundante? Um bom treinador pode inspirar uma virada inesperada em sua equipe, mas quando se trata de otimização, não podemos simplesmente fazer com que esses sistemas "se esforcem mais". Trata-se de compreender a informação com que eles lidam e como a comunicam.

Isso se resume a otimizar as chamadas de desenho que a CPU envia para a GPU. Quanto mais trabalho pudermos incluir em uma única chamada, melhor, especialmente quando há dezenas de milhares de objetos para renderizar.

Existem muitos truques para conseguir isso – mas uma palavra de cautela antes de começar.

Não otimize de forma indiscriminada, apenas pela emoção de um código inteligente. Sempre comece por avaliar a viabilidade do processo. Identifique onde seu projeto está sofrendo mais. A primeira pergunta que você sempre deve fazer: O gargalo está na CPU ou na GPU?

Algumas das soluções neste post aumentam a velocidade da CPU, outras a velocidade da GPU. Não se empolgue demais otimizando um processador quando o outro é, na verdade, a fonte dos picos de quadros. Após determinar se o seu jogo é limitado pela CPU ou pela GPU, investigue qual procedimento está demorando mais e otimize-o. O guia de melhores práticas de criação de perfis da Unity é um ótimo ponto de partida, incluindo um fluxograma prático que oferece orientações sobre o processo, muitas vezes misterioso, de criação de perfis.

“Tenho que fazer muita análise de perfil”, diz Liam. "Consigo perceber quando a CPU está a trabalhar muito e a GPU não, e vice-versa." Na verdade, nosso maior gargalo tem sido ambos, em momentos diferentes.”

Incluímos uma série de nossos recursos favoritos no final deste post para ajudar você em sua jornada de criação de perfis.

Feita essa ressalva, vamos explorar as otimizações.

Simplificar e eliminar

Ao renderizar, precisamos determinar quais malhas renderizar e onde.

Quanto mais malhas tivermos e mais chamadas de desenho precisarmos, mais a CPU terá que ficar decidindo o que fazer enquanto a GPU espera pela próxima tarefa.

Poderíamos acelerar o processo renderizando menos malhas. Por exemplo, você poderia substituir malhas complexas por versões falsas, outdoors ou versões com poucos polígonos; ou poderia dividir um mundo extenso em níveis menores, com menos elementos para renderizar simultaneamente. Essas são soluções comprovadas que você deve usar sempre que possível, mas elas limitam o nível de detalhamento dos seus ambientes.

Uma otimização que evita isso, e é simples de implementar, é a eliminação por oclusão, onde a câmera verifica o que está dentro de seu campo de visão e evita renderizar o que o jogador não pode ver. Isso economiza tempo, mas aumenta o uso de memória. No entanto, muitas vezes vale a pena em ambientes com muitas malhas estáticas, como salas detalhadas em um prédio de escritórios. Essa otimização é um padrão da indústria, mas muitas vezes não é suficiente por si só.

loteamento estático

Outra forma de limitar o número de malhas que renderizamos sem sacrificar a variedade é combiná-las em uma única malha.

Você pode fazer isso manualmente. Ou, desde que as malhas compartilhem o mesmo material, o Unity pode fazer isso para você em um processo chamado processamento em lote. Defina um objeto de jogo como estático e o Unity agrupará automaticamente todas as malhas com o mesmo material para reduzir as chamadas de desenho. Use essa opção em tudo que permanecer estático, como árvores e paredes.

Isso reduz drasticamente o uso de RAM e a sobrecarga da CPU, permitindo que a GPU renderize mais conteúdo simultaneamente. Mas lembre-se de que mais memória da GPU será usada para armazenar as malhas combinadas.

O agrupamento estático costuma ser nosso principal processo de otimização, especialmente para o Backyard Baseball . Utilizar o sistema de produção em lotes da URP é simples, portanto, o maior desafio é descobrir como usar a menor quantidade possível de materiais no maior número possível de modelos. Esse equilíbrio é o que nos permite ter alguns dos profissionais mais criativos em nossas equipes de otimização e arte.

Instanciamento de GPU

Este é um bom momento para começar a distinguir entre uma coisa... e uma instância dessa coisa.

Digamos que você tenha uma malha. Uma malha é um recurso valioso. E seu material é uma vantagem. São arquivos individuais que existem na sua estrutura de arquivos. Para cada objeto com aparência 3D no seu jogo, uma malha descreve sua forma e um material descreve a aparência de sua superfície.

Mas, como o Unity simplifica seus detalhes, alguns desenvolvedores não percebem que, quando o jogo está em execução, eles têm, na verdade, várias cópias desses elementos instanciadas em seu mundo de jogo. Quando o jogador explora uma floresta, ele está se movendo através de várias cópias daquela árvore, armazenadas como um recurso nos arquivos do jogo.

É por isso que usamos instanciação de GPU para a folhagem em Backyard Baseball . Em vez de renderizar cada cópia da árvore com chamadas únicas à GPU, a CPU solicita à GPU que renderize todos os modelos idênticos de uma só vez. Se você não tomar cuidado, isso pode resultar em todas as árvores da floresta parecendo idênticas. Mas, com alguns parâmetros eficazes no shader do material, por exemplo, um valor para personalizar a cor das folhas, você pode passar para a GPU um modelo e material, juntamente com as cores exclusivas para cada árvore, em vez de solicitar cada árvore individualmente.

A folhagem costuma ser uma boa candidata para instanciação em GPU.
A folhagem costuma ser uma boa candidata para instanciação em GPU.

Ao ativar a opção "Habilitar Instância" em um material, você instrui o Unity a combinar em uma mesma chamada de desenho diferentes instâncias de materiais que utilizam o mesmo material. Essa é uma ótima maneira de equilibrar variação e desempenho em suas malhas. E, ao contrário do processamento em lote estático, a instanciação por GPU pode ser usada em objetos do jogo que se movem na sua cena, então você não está restrito a otimizar apenas coisas como paredes e árvores, mas também objetos como destroços de um acidente ou materiais de escritório.

Texturas de animação de vértices

O processamento em lote estático e a instanciação em GPU são duas maneiras diferentes de otimizar malhas e materiais. Às vezes, porém, são as animações que causam o gargalo. Considere o exemplo simples da floresta mencionado anteriormente. Agora, imagine seus galhos e folhas balançando ao vento, tudo com uma animação única e natural. Executar 10.000 processos de animação únicos da maneira usual simplesmente não será suficiente. O pobre processador vai ficar sem ar se você não tomar cuidado!

Um truque é usar texturas de animação de vértices (VAT). Um VAT sequestra o poder de processamento de uma GPU para tentar fazer animação.

Para David Chávez Armenteros, desenvolvedor sênior da Mega Cat Studios, usar o VAT (Veículo de Agregados Tecnológicos) para simular uma multidão foi uma de suas implementações gráficas favoritas para otimizar.

“Usando renderizadores de malha com esqueleto padrão com o Animator, você só consegue renderizar algumas dezenas de personagens antes que o desempenho comece a cair”, diz ele. “Mas, ao combinar VAT com instanciação de GPU, você pode exibir milhares de entidades animadas na tela simultaneamente.”

Com o VAT, cada vértice da malha lê sua posição animada a partir de uma textura a cada quadro. Para isso, codificamos dados posicionais e rotacionais em valores RGB . Em seguida, um shader especial lê todos os pixels de uma textura para determinar como mover todos os vértices.

Foi isso que usamos para a grama balançando no jogo Backyard Baseball . É uma maneira eficiente de criar animações suaves, mas lembre-se, é puramente visual – o colisor não muda. Isso torna o VAT ideal para cenários onde o movimento é essencial, mas a detecção precisa de colisões não é.

Em Backyard Baseball, o balanço da grama é obtido através de texturas de animação de vértices (VAT).
Em Backyard Baseball, o movimento da grama é obtido através de texturas de animação de vértices (VAT).

E toda otimização tem um preço. O VAT libera a CPU, ao custo de uma carga adicional na RAM. Tudo isso precisa ser equilibrado com outras soluções de renderização no jogo.

“O aspecto mais complexo do sistema foi equilibrar o uso de memória e os cálculos de eliminação de jogadores baseados em computação gráfica para lidar com os recursos limitados de dispositivos sem fio”, afirma Jordan Latta, artista técnico de Backyard Baseball .

URP vs HDRP

A primeira escolha que você faz ao otimizar gráficos é qual pipeline de renderização escolher ao iniciar um projeto. O Universal Render Pipeline (URP) possui um bom desempenho básico e é absolutamente essencial para dispositivos móveis e sem fio. O High Definition Render Pipeline (HDRP) tem como alvo visuais de alta fidelidade e oferece um comportamento de instanciação mais especializado.

Em geral, recomendamos o uso de URP em vez de HDRP no Unity. Talvez você tenha um caso de uso que exija HDRP, mas somos motivados por este princípio simples: Mantenha sua renderização o mais eficiente possível.

O HDRP oferece alguns recursos avançados, mas se você sabe que não está buscando fidelidade visual realista, recomendamos que não o utilize.

Mais truques de otimização

Às vezes, o problema de ter milhares de objetos na tela não é a renderização em si. É o seu próprio código. Nesses casos, aqui estão alguns truques que você pode usar:

  • Consolide milhares de loops de atualização em um só. Em vez de atribuir um MonoBehaviour a cada GameObject, consolide-os em um só para que compartilhem a mesma função Update. Um gerenciador centralizado ajuda a evitar milhares de ciclos de atualização individuais.
  • Em vez de executar tudo na mesma thread, use multithreading. Analise se o sistema de tarefas e o compilador Burst podem ser boas opções para o seu jogo.
  • Ganhe dinheiro com os caches. Em vez de obter a câmera principal ou o Transform de um GameObject a cada quadro, armazene-os em cache uma única vez e reutilize essa referência. Tarodev demonstra a melhoria de desempenho e explica também essas outras otimizações.

Talvez a melhoria de renderização mais significativa que você possa obter para o seu próximo projeto seja usar a versão LTS mais recente do Unity. O Unity 6.3 LTS apresenta uma série de melhorias, incluindo otimizações para melhorar o desempenho.

Para o Backyard Baseball , a nossa solução de otimização mais simples e eficaz foi controlar o uso de texturas.

Existem algumas maneiras sorrateiras de usar acidentalmente o dobro das texturas necessárias:

  • Shaders : Se um shader usar uma textura em duas ocasiões diferentes, e o fizer sem compartilhar a mesma referência, ele poderá carregar a textura em vários locais da memória.
  • Roteiros : Da mesma forma, diferentes áreas do seu código podem acabar carregando a mesma textura por meio de referências diferentes.
  • Version Control : Quando dois desenvolvedores adicionam o mesmo arquivo à sua branch local, às vezes ambos os arquivos são mantidos quando as branches são mescladas, ocupando espaço de armazenamento redundante.

Procuramos estar atentos a essas armadilhas para que possamos evitá-las antes mesmo que aconteçam, mas ser muito rigoroso acaba por atrasar o ciclo de iteração acelerado. É aí que entram nossos especialistas em otimização para auditar shaders, recursos e scripts quando o projeto entra nas fases finais do seu ciclo de desenvolvimento.

Na Mega Cat Studios , essas estratégias nos permitem renderizar cenas que eram impensáveis ​​há apenas alguns anos.

Para nós, a renderização é basicamente mágica: podemos criar qualquer coisa que imaginarmos em tempo real, mas somente após estudar cuidadosamente os textos secretos (documentação da Unity , posts em blogs, tutoriais do YouTube). Por sorte, temos alguns gênios na nossa equipe que adoram mergulhar nessa documentação e compartilhar os resultados com o time.

E, claro, quem realmente se beneficia são os nossos jogadores. Esperamos que os fãs se divirtam explorando o Backyard Baseball sem nem pensar em quanto sangue, suor e magia foram necessários para tornar esse mundo tão real.

Saiba mais