Como o SEED renderiza um mundo os jogadores nunca param de construir
Adam Axler - Unity
Senior Content Marketing Manager

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.
Você não pode prever o que os jogadores vão construir. Em SEED, esse é o ponto principal – e o desafio central de renderização.
SEED é o sandbox MMO persistente da Klang Games, construído com Unity. É ambientado em um planeta distante onde os jogadores gerenciam personagens autônomos chamados mudas, constroem casas e negócios, negociam em uma Economy impulsionada por jogadores e organizam sociedades com seus próprios papéis e leis. O mundo continua a funcionar depois que os jogadores saem, e está crescendo continuamente. Cada nova casa, loja, árvore e muda coloca mais pressão no desempenho de renderização da Unity, em hardware que varia de PCs de ponta a telefones.
A simulação em si roda nos servidores da Klang Games. O trabalho do cliente Unity é renderizar qualquer estado que o servidor transmita, então sua carga de trabalho depende do que os jogadores construíram, e não do que a equipe planejou.
"Como SEED é um jogo totalmente autoritativo no servidor, o cliente principalmente lê e renderiza o estado e encaminha interações do jogador, como clicar ou movimento da câmera," diz Artem Dyadichkin, engenheiro gráfico da Klang Games.
Conversamos com Dyadichkin e Nikita Fetisov, engenheiro de jogos sênior, sobre a renderização de sociedades construídas pelo jogador com o Universal Render Pipeline (URP), mantendo milhares de objetos pequenos baratos e usando dados reais do jogador para encontrar gargalos em PC e mobile.

Um mundo construído a partir de pedaços minúsculos
O estilo artístico de SEED faz grande parte do trabalho de escalonamento antes que qualquer código seja executado. O jogo é estilizado e de baixa poligonagem, e em vez de depender de texturas, ele armazena a maior parte de seus dados de superfície na geometria.
"A maior parte dos nossos dados de cor é, na verdade, armazenada dentro dos dados do vértice", diz Dyadichkin. "Os dados do vértice sabem qual cor é, qual definição de material ele tem – é metal, é liso?" Todas aquelas coisas estão incorporadas nas próprias malhas.
Isso economiza em sombreamento e largura de banda de memória, o que é mais importante em dispositivos móveis.
Prédios levam a mesma abordagem ao extremo. Em vez de tratar cada estrutura como uma única malha grande, SEED constrói edifícios a partir de muitos módulos pequenos, semelhantes a tijolos: paredes, pisos, bordas de telhado e cantos em uma grade de um metro. Os jogadores colocam blocos de construção grosseiros (voxels), e o jogo expande cada um deles em cerca de 15 módulos, aproximadamente metade formando o exterior do edifício e metade o seu interior, que é gerado apenas quando um jogador olha para dentro. A maior sociedade em uma das ilhas mais movimentadas de SEED tem 172 edifícios, compostos por aproximadamente 12.500 voxels, ou 190.000 módulos.
"Nós utilizamos BatchRendererGroup para renderizá-los e agrupá-los juntos, e fazemos esses lotes através de jobs," diz Dyadichkin. "Mesmo que haja muitos módulos que precisamos renderizar, os edifícios em si nunca foram um gargalo em termos de desempenho de renderização puro."
Esses trabalhos rodam no C# Job System, e a equipe os compila com o Burst compiler. Dyadichkin diz que eles quase sempre andam juntos no código do cliente do SEED’.

SEED | Klang Games
Permanecendo no caminho padrão no URP
SEED usa URP para escalar em PC e mobile, e a Klang Games deliberadamente se mantém próximo aos padrões do Unity.
"Nós tentamos aderir às soluções padrão da Unity, para que sempre possamos ter certeza de que, quando a próxima atualização chegar, ela será coberta," diz Dyadichkin.
Isso importa porque a equipe atualiza o Unity aproximadamente uma ou duas vezes por ano – SEED atualmente roda no Unity 6.3 – adotando novos recursos de renderização à medida que o projeto cresce. Onde o jogo precisa de algo personalizado, a equipe estende o URP em vez de substituí-lo, usando recursos de renderizador personalizados para efeitos e interações específicos do jogo.
O uso de Shader Graph segue o mesmo princípio. Os ativos da natureza usam o shader padrão Lit shader, enquanto personagens e objetos usam shaders Unlit com uma passagem de iluminação personalizada. De qualquer forma, a equipe não precisa se preocupar em prejudicar os recursos de desempenho do URP.
"Você pode ter certeza de que se você criar um Shader Graph, ele não quebrará o agrupamento do SRP [Scriptable Render Pipeline], e não quebrará o GPU Resident Drawer," diz Dyadichkin. "Ter certeza de que todos os recursos centrais do URP ainda são suportados, enquanto você ainda tem espaço para personalizar o que quiser em um shader, é muito poderoso."
Essa rede de segurança importa em um mundo onde os jogadores, e não os designers, decidem quanto o cliente tem que desenhar.
Interagindo com milhares de objetos
Quanto mais densos os jogadores constroem, mais difícil fica renderizar uma sociedade – e deixá-los clicar em qualquer parte dela.
Quando os jogadores estão ampliados, SEED usa seleção pixel-perfeita. Um recurso de renderizador personalizado desenha objetos em um alvo de renderização separado, uma textura fora da tela na qual a GPU renderiza em vez da tela. Cada objeto é codificado com um ID exclusivo que tanto a CPU quanto a GPU podem ler. O cliente lê o pixel sob o cursor para descobrir exatamente qual objeto o jogador está pairando.
No celular, a ponta do dedo é muito menos precisa que um cursor, então o cliente também verifica os pixels ao redor de cada toque. Se detectar mais de um objeto por perto, mostra ao jogador uma lista para escolher, facilitando a seleção de objetos menores em áreas densamente construídas.
Quando os jogadores dão zoom para fora, o cliente volta para os raycasts de física, pois a seleção por GPU é mais difícil de escalar em uma visão ampla.
Por trás desses raycasts há um enorme número de colisores. SEED usa Unity Physics não para simulação, mas para inicializá-los rapidamente e consultá-los.
"Cada árvore tem um colisor, cada objeto e potencialmente cada tijolo de construção pode ter um, e personagens e mudas também têm," diz Dyadichkin. "Podemos inicializar essa grande quantidade de colisores muito rapidamente e então fazer consultas contra eles para verificações de posicionamento e outras interações."
Uma vez que um jogador abre um edifício, seu interior aparece, e o cliente tem mais a rastrear enquanto se move entre andares e inspeciona cômodos individuais. Um trabalho em execução contínua determina se cada objeto está dentro ou fora de um prédio e em qual cômodo e andar ele se encontra.
"Isso nos permite fazer todo tipo de coisas – desativar ou ativar GameObjects, ou definir as camadas de renderização corretas para controlar a situação de iluminação," explica Dyadichkin.

SEED | Klang Games
Perfilando os jogadores do mundo que realmente construíram
A parte mais difícil de otimizar para mundos construídos pelos jogadores é obter dados realistas. Klang Games obtém do jogo ao vivo.
A equipe mantém instantâneos do servidor para recuperação de desastres, e quando os jogadores constroem sociedades grandes o suficiente, esses instantâneos se tornam casos de teste.
"Podemos restaurar o que os jogadores realmente construíram e usar isso para testes de desempenho e testes de recursos em escala", diz Fetisov. "Podemos trabalhar com essas sociedades pré-construídas em vez de começar do zero ou tentar simular os dados nós mesmos."
Carregar um snapshot de uma cidade grande expôs um gargalo de renderização inesperado de CPU no PC.
"Nosso jogo não é gargalo de GPU na maioria das vezes, mas sim gargalo de CPU", diz Dyadichkin. É um jogo muito estilizado, de baixa poligonagem, com quase nenhuma textura.
Usando o Unity Profiler, Dyadichkin descobriu que o thread de renderização estava gastando mais tempo do que o esperado enviando chamadas de desenho. A equipe usa GPU Resident Drawer, então Dyadichkin esperava que ele instanciasse esses objetos. O Frame Debugger mostrou o contrário.

SEED | Klang Games
"Nós ainda estávamos usando o agrupamento SRP em vez do agrupamento híbrido," diz Dyadichkin. "Acontece que o GPU Resident Drawer não estava capturando todos esses objetos porque quase todos os nossos Prefabs têm Grupos LOD."
A diferença importa na escala de SEED. O SRP Batcher reduz o custo da CPU ao configurar cada chamada de desenho, mas ainda envia uma por objeto. O Drawer Residente da GPU vai além, agrupando objetos que compartilham uma malha e material em chamadas de desenho instanciadas, que o Frame Debugger rotula como lotes híbridos. Com milhares de objetos pequenos, essa é a diferença entre muitas chamadas de desenho leves e algumas grandes.
O culpado pelos objetos perdidos foi a transição de LOD animada. O efeito parecia melhor, mas mantinha os objetos fora do caminho do Gaveteiro Residente da GPU.
Nós desativamos a parte da animação. Nós ainda temos cross-fading, mas agora com transições definidas manualmente," ele diz. "Agora as chamadas de desenho são instanciadas novamente, o que aliviou a carga no nosso thread de renderização da CPU."

SEED | Klang Games
Renderizando uma sociedade madura na memória móvel
No celular, a renderização de SEED atingiu uma restrição diferente. "No lado móvel, não estamos limitados pela CPU – estamos limitados pela memória", diz Fetisov. "Esse é o principal calcanhar de Aquiles do nosso projeto."
Uma sociedade madura pode conter enormes números de edifícios, objetos externos, personagens e malhas. Cada malha e material que o cliente renderiza tem que caber na memória primeiro. A Klang Games depende muito do Memory Profiler e das comparações de snapshot de memória para rastrear onde essa memória vai. A equipe encontrou texturas armazenadas três vezes devido a uma referência quebrada, dependências Addressables que duplicavam o mesmo material e Collections C# muito maiores do que o necessário.
"Muitas coisas surgiram onde, no desktop, estava tudo bem e as pessoas não notaram, mas no celular foi um grande problema", diz Fetisov. "Nós dependemos muito do Unity Memory Profiler, especialmente das diferenças de instantâneos de [memória]."
Mesmo sem texturas, a geometria soma.
"Alguns dos malhas eram bem grossos, especialmente as árvores", diz Fetisov. "Se você carregar todos os LODs, uma única árvore pode consumir megabytes de memória, e nós temos muitas variações de árvores."
Como a equipe compila Addressables por plataforma, ela pode enviar árvores simplificadas para dispositivos móveis sem alterar nenhum código do jogo. "O mesmo código que carrega a cadeira no desktop carrega a cadeira no celular", explica Fetisov. "Mas os Addressables em si podem ser assets otimizados para dispositivos móveis."
A mudança maior foi substituir os Grupos LOD no celular por completo. Os LODs clássicos significavam armazenar múltiplos malhas por tipo de objeto na memória – o mesmo custo que Fetisov descreve com as árvores. Mesh LOD, introduzido no Unity 6.2, armazena em vez disso cada nível de detalhe dentro de uma única malha, e as variantes móveis do SEED agora o utilizam exclusivamente. Também reduziu a carga de trabalho da pequena equipe de arte da Klang Games.
"Mudar de LODs para LOD de Malha foi um passo crucial para tornar possível renderizar o mundo do jogo em dispositivos móveis", diz Fetisov.

SEED | Klang Games
Projetando para o que os jogadores construirão a seguir
O desafio central de renderização do SEED não vai desaparecer: Os jogadores decidem o que o cliente tem que desenhar, e eles nunca param de construir. "É um equilíbrio constante entre a fidelidade visual que imaginamos para esses mundos criados pelos jogadores e taxas de quadros estáveis em dispositivos de baixo desempenho", diz Dyadichkin.
Klang Games não pode prever o que os jogadores construirão a seguir – mas pode testar contra o que eles já construíram.
"Projete, construa e teste para sua escala alvo desde o primeiro dia", diz Fetisov. "Perfil contra cargas realistas cedo e continue fazendo isso."
SEED está disponível em acesso antecipado. Confira mais histórias de desenvolvedores da Unity no Blog da Unity e no Resource Hub.