2D Pixel Perfect: Como configurar seu projeto Unity para jogos retrô de 8 bits

Leve sua experiência de desenvolvimento 2D para o próximo nível e explore o conjunto nativo de ferramentas 2D da Unity.
Os jogos retrô com mecânica simples e gráficos pixelados podem evocar boas lembranças para os jogadores veteranos e, ao mesmo tempo, ser acessíveis ao público mais jovem. Hoje em dia, muitos jogos são rotulados como "retrô", mas é preciso esforço e planejamento para criar um título que realmente tenha aquela aparência e sensação nostálgica. Por isso, convidamos o pessoal da Mega Cat Studios para nos ajudar a falar sobre o assunto. Nesta postagem do blog, abordaremos tudo o que você precisa para criar arte autêntica para jogos no estilo NES, incluindo configurações importantes do Unity, estruturas gráficas e paletas de cores. Obtenha nosso projeto de amostra e acompanhe-o!

A Mega Cat Studios, de Pittsburgh, Pensilvânia, transformou a criação de jogos retrô altamente precisos em uma forma de arte. Tanto que, na verdade, vários de seus títulos também podem ser adquiridos em forma de cartucho e jogados em consoles retrô, como o Sega Genesis.

As recentes adições aos fluxos de trabalho do Unity o tornaram um ambiente adequado para a criação de seus jogos retrô. O sistema de mapa de azulejos 2D ficou ainda melhor e agora suporta mapas de azulejos em grade, hexagonais e isométricos! Além disso, você pode usar o novo componente Pixel Perfect Camera para obter movimentos e visuais consistentes baseados em pixels. Você pode até mesmo usar o Post Processing Stack para adicionar todos os tipos de efeitos de tela retrô legais. No entanto, antes que qualquer um desses trabalhos possa ser feito, seus ativos precisarão ser importados e configurados corretamente.
Nossos ativos precisam primeiro de uma configuração correta para serem nítidos e claros. Para cada ativo que estiver usando, selecione o ativo na visualização Projeto e, em seguida, altere as seguintes configurações no inspetor:
- Modo de filtro alterado para "Ponto
- Compressão alterada para "Nenhuma

Outros modos de filtro resultam em uma imagem levemente borrada, o que arruína o estilo nítido de pixel-art que estamos procurando. Se a compactação for usada, os dados da imagem serão compactados, o que resulta em alguma perda de precisão em relação ao original. É importante observar isso, pois pode fazer com que alguns pixels mudem de cor, possivelmente resultando em uma alteração na própria paleta de cores geral. Quanto menos cores e quanto menor for o sprite, maior será a diferença visual causada pela compactação. Aqui está uma comparação entre a compactação normal (padrão) e nenhuma compactação.

Outro aspecto a ser observado é a configuração do tamanho máximo da imagem no Inspector. Se a imagem do sprite tiver um tamanho em qualquer eixo maior do que a propriedade "Max Size" (2048 por padrão), ela será automaticamente redimensionada para o tamanho máximo. Isso geralmente resulta em alguma perda de qualidade e faz com que a imagem fique embaçada. Como alguns hardwares não suportam adequadamente texturas acima de 2048 em nenhum dos eixos, é uma boa ideia tentar ficar dentro desse limite.

Acima, há um sprite de uma folha de sprites que tinha 2208 em um eixo com tamanho máximo definido em 2048. Como você pode ver, aumentar a propriedade Max Size para 4096 permite que a imagem seja dimensionada adequadamente e evita a perda de qualidade.
Por fim, ao preparar seu sprite ou folha de sprite, certifique-se de definir o modo de unidade de pivô como "Pixels" em vez de "Normalizado".

Isso ocorre para que o ponto de articulação do sprite seja baseado em pixels em vez de um intervalo suave de 0 a 1 em cada eixo da imagem. Se o sprite não girasse exatamente a partir de um pixel, perderíamos a perfeição do pixel. Os pivôs podem ser definidos para sprites no Sprite Editor, que pode ser aberto no Inspector quando você tiver um ativo de sprite selecionado.

Com os ativos preparados, podemos configurar nossa câmera para ficar "perfeita em termos de pixels". Um resultado perfeito em termos de pixels terá uma aparência limpa e nítida. Sinais reveladores de pixel art que não são exibidos como pixel perfeito incluem desfoque (aliasing) e alguns pixels que parecem retangulares quando deveriam ser quadrados.
O pacote 2D Pixel Perfect pode ser importado por meio do Package Manager no Unity. Clique no menu "Window" (Janela) na barra de ferramentas e, em seguida, em "Package Manager" (Gerenciador de pacotes). Na nova janela, clique em "Advanced" (Avançado) e verifique se você ativou "Show preview packages" (Mostrar pacotes de visualização). Selecione 2D Pixel Perfect na lista à esquerda e selecione instalar no canto superior direito da janela.

É isso aí. Agora você está pronto para começar a usar o componente de câmera com pixels perfeitos.
O componente Pixel Perfect Camera é adicionado e aumenta o componente Camera do Unity. Para adicioná-lo, vá até a câmera principal e adicione o componente Pixel Perfect Camera a ela. Se a opção do componente Pixel Perfect Camera não estiver lá, siga as instruções mencionadas anteriormente para importá-lo primeiro para o projeto.

Agora vamos dar uma olhada nas configurações que temos disponíveis.

Primeiro, recomendo marcar a opção "Run In Edit Mode" (Executar no modo de edição) e definir a proporção da tela na visualização do jogo como "Free Aspect" (Aspecto livre) para que você possa redimensionar a visualização do jogo livremente. O componente exibirá mensagens úteis na visualização do jogo explicando se a tela não é perfeita em termos de pixels em uma determinada resolução.

Agora, você pode examinar cada configuração para ver o que elas fazem e como afetam a aparência do seu jogo!
- Assets Pixels Per Unit (Pixels por unidade de ativos ) - Esse campo faz referência à configuração que você pode selecionar no inspetor para cada ativo. Como regra geral, cada ativo que será usado no espaço do mundo do jogo deve usar os mesmos pixels por unidade (PPU), e você também colocaria esse valor aqui. Se o mundo do seu jogo existir como uma grade de blocos e sprites, cada um com 16 pixels por 16 pixels, uma PPU de 16 faria sentido - cada bloco da grade seria uma unidade nas coordenadas do espaço mundial. Certifique-se de colocar a PPU escolhida aqui.
- Reference Resolution (Resolução de referência ) - Defina essa opção como a resolução em que você deseja que todos os seus ativos sejam visualizados. Se você quiser um visual retrô, isso geralmente significa uma resolução muito pequena. Por exemplo, a resolução nativa do Sega Genesis é 320x224. Ao portar um jogo do Sega Genesis, usaríamos uma resolução de referência de 320x224. Para uso geral em 16:9, 320x180 e 398x224 (se você quiser manter a resolução vertical) devem funcionar bem.
- Upscale Render Texture - Isso faz com que a cena seja renderizada o mais próximo possível da resolução de referência e, em seguida, seja redimensionada para se ajustar ao tamanho real da tela. Como essa configuração resulta em uma tela cheia, recomendamos que a use se quiser uma experiência de tela cheia perfeita em termos de pixels e sem margens. A opção "Upscale Render Texture" também afetará significativamente a aparência dos sprites quando girados.

- Pixel Snapping (disponível apenas com a opção Upscale Render Texture desativada) - Com essa opção ativada, os renderizadores de sprite serão encaixados automaticamente em uma grade de espaço mundial, em que o tamanho da grade é baseado na PPU escolhida. Observe que isso não afeta de fato as posições de transformação de nenhum objeto. Como resultado, você ainda pode interpolar suavemente os objetos entre as posições, mas o movimento visual permanecerá perfeito em termos de pixels e rápido.
- Exemplo:

- Crop Frame (X e Y) - Corta a região visualizada do espaço mundial para corresponder exatamente à resolução de referência e adiciona margens pretas à exibição para preencher as lacunas nas bordas da tela.
- Stretch Fill (Esticar preenchimento ) - Fica disponível se você ativar x e y para Crop Frame (Cortar quadro). Isso faz com que a câmera seja dimensionada para a visualização do jogo para caber na tela de uma forma que preserve a proporção. Como esse dimensionamento não ocorrerá apenas em múltiplos de números inteiros da resolução de referência, ele fará com que a perfeição dos pixels seja perdida em qualquer resolução que não seja um múltiplo de números inteiros da resolução de referência. A vantagem aqui é que, embora você perca a perfeição dos pixels em muitas resoluções, não terá as margens da barra preta e, em vez disso, terá uma tela totalmente preenchida. Observe que, embora o embaçamento ocorra com frequência devido ao preenchimento de trecho, a mensagem de exibição de alerta usual não é exibida.

Se você quiser uma tela com pixels perfeitos e rápida que funcione para uma variedade de casos de uso, eu recomendo:
- Use uma resolução de referência que nunca será maior do que a resolução da janela do jogador (por exemplo, 320x180).
- Ativar ou desativar a textura de renderização Upscale
- Ative-o se você for usar rotações fora de 90, 180 e 270 e se preferir o efeito visual que ele produz em sprites girados.
- A textura de renderização ampliada pode resultar em uma imagem sem pixels perfeitos em algumas resoluções, dependendo de sua resolução de referência. Faça experiências com isso e com diferentes resoluções de tela usando a opção "Executar no modo de edição" ativada no Pixel. Componente Perfect Camera para determinar se isso é um problema para a sua resolução. Se conseguir produzir uma imagem com pixels perfeitos em todas as resoluções de destino, isso resultará na melhor experiência de tela cheia com pixels perfeitos.
- Ativar ou desativar o Pixel Snapping conforme sua preferência
- Isso é mais uma preferência pessoal do que qualquer outra coisa. Sem o snapping, o movimento é muito mais suave, mas os pixels podem ficar desalinhados.
- Habilite Crop Frame X e/ou Y se não estiver usando Upscale Render Texture
- Se não conseguir obter consistentemente um resultado perfeito em termos de pixels com a textura de renderização upscale, o corte X e/ou Y garantirá uma imagem perfeita em termos de pixels para qualquer resolução maior que a resolução de referência, mas criará grandes margens nas bordas da tela para algumas resoluções.
- Desativar o preenchimento de estiramento
Recomendamos configurar a câmera para ser otimizada para visualização na proporção 16:9, incluindo a resolução de referência, se possível. No momento em que este artigo foi escrito, a maioria dos gamers jogava em monitores 16:9 e com resolução de 1920x1080. Por exemplo, a resolução de referência de 320x180 é 16:9 e, portanto, não terá margens de barra preta quando reproduzida em 1920x1080 ou em qualquer resolução que seja um múltiplo uniforme de 320x180, como 1280x720.
Na barra de ferramentas do Unity, você pode ir em Edit > Project Settings > Player e limitar as proporções de aspecto que o jogo suportará. Se você achar que uma determinada configuração funciona exatamente como deseja na proporção desejada, mas fica ruim em algumas proporções específicas, é possível impedir que a janela fique nessas proporções aqui. No entanto, lembre-se de que nem todos os usuários terão uma configuração de monitor que funcione bem com suas limitações, portanto, isso não é recomendado. Em vez disso, ative o corte para que esses usuários tenham margens, em vez de terem que jogar em uma resolução que não se ajusta à tela deles.
Agora que já falamos sobre como configurar a Unity para obter uma arte perfeita em pixels, vamos dar uma olhada nos princípios básicos da criação de arte para jogos que seguem as restrições do clássico Nintendo Entertainment System. Essa geração de console impõe um grande número de restrições aos artistas que tentam criar uma imagem autêntica. Essas restrições incluem itens como paletas usadas e o tamanho e a quantidade de objetos em uma tela. Além disso, é importante ter em mente a resolução de referência de 256x240 ao "mirar" esse console.
Ao criar um trabalho artístico genuíno para o NES, há uma série de restrições que o artista deverá seguir. Alguns deles serão consistentes, independentemente do console retrô que o artista estiver tentando emular, enquanto muitos outros são específicos do próprio NES. A primeira e possivelmente a mais importante dessas restrições envolve a maneira como as paletas de cores são usadas em uma imagem. O NES é bastante singular quando se trata de sua paleta de cores, pois a paleta de cores completa do console está codificada no console. O NES escolhe as cores a serem usadas em uma imagem enviando uma série de valores para o processador gráfico no NES e, em seguida, o processador gráfico retorna as cores associadas a esses valores. Abaixo está uma imagem da paleta de cores do NES:

Essas cores não podem ser alteradas porque fazem parte do próprio console. Todos os jogos que você já viu para esse console usam combinações dessas cores para criar suas imagens.
Para criar as combinações usadas no jogo, são criadas subpaletas e atribuídas aos sprites do jogo ou aos elementos do plano de fundo. O NES divide sua paleta em subpaletas que podem ser atribuídas a sprites e planos de fundo. Cada sub-paleta inclui uma cor comum que é usada em todas as sub-paletas e três cores exclusivas. Ele é capaz de carregar quatro sub-paletas para os planos de fundo e quatro sub-paletas para os sprites. No caso dos sprites, a cor comum no início de cada sub-paleta é tratada como transparência.

Este é um exemplo de uma série de sub-paletas que estão sendo usadas em um jogo. A linha superior representa as sub-paletas de plano de fundo e a linha inferior representa as sub-paletas de sprite. Neste exemplo, o preto está sendo usado como a cor comum que é compartilhada em todas as subpaletas. Como a cor comum é tratada como transparência nos sprites, é necessário criar uma segunda entrada na paleta preta para as subpaletas dos sprites, a fim de usá-la como uma cor visível.
As restrições ao uso da paleta ficam ainda mais rígidas à medida que o artista passa a ver como as paletas são usadas no jogo. Para explicar isso, é preciso discutir mais sobre como os consoles retrô armazenam, usam e exibem a arte. A arte de qualquer console retrô é armazenada no jogo como blocos de 8x8 px. O uso dessa abordagem baseada em ladrilhos permite que os artistas economizem espaço reutilizando os ladrilhos para coisas diferentes. (Por exemplo, pedaços de uma calçada podem ser reaproveitados e usados para fazer a borda de um edifício). Outro aspecto importante a ser observado sobre o armazenamento baseado em blocos é que as informações de cores geralmente não são salvas com os gráficos. Todos os ladrilhos são salvos com uma paleta monocromática. Dessa forma, sempre que um bloco for exibido no jogo, ele poderá ter uma subpaleta atribuída a ele, permitindo que o mesmo bloco seja exibido simultaneamente na tela com diferentes subpaletas. Isso é importante ao criar um trabalho artístico fiel a um console retrô em uma plataforma moderna, pois afeta a forma como as paletas são atribuídas ao trabalho artístico.
O NES atribui paletas a sprites e planos de fundo de forma diferente. Ele atribui sub-paletas para sprites em uma base de ladrilho por ladrilho. Isso significa que cada bloco 8x8 em um sprite pode ter uma das quatro sub-paletas de sprite atribuídas a ele.

Os planos de fundo, por outro lado, são muito mais restritivos. Os planos de fundo atribuem suas paletas em blocos de 16x16. As atribuições da subpaleta para o fundo de uma tela inteira são chamadas de tabelas de atributos. Essas tabelas de atributos são a razão pela qual a maioria das obras de arte retrô envolve o uso intenso de segmentos de ladrilhos repetidos. Esses segmentos tendem a ser compostos de blocos de 16x16 para que se encaixem perfeitamente em uma tabela de atributos. Apesar de ser uma resposta a uma restrição de hardware, essa abordagem baseada em blocos de 16x16 para planos de fundo acabou se tornando uma característica definidora da arte retrô e é absolutamente necessária quando se tenta recriá-la.

Embora os artistas sejam livres para usar diferentes subpaletas para cada bloco 8x8 de um sprite, eles podem se encontrar em uma situação em que desejam ter uma profundidade de cor maior em um sprite do que a que já está disponível. É nesse ponto que as camadas de sprite podem ser úteis. A estratificação de sprite consiste simplesmente em dividir um sprite em dois sprites separados e colocá-los um sobre o outro. Isso permite que os artistas contornem a restrição de uma sub-paleta por bloco 8x8. Isso basicamente permitirá que os artistas dobrem o número de cores que podem ser usadas em uma única área 8x8. A única grande desvantagem de fazer isso são os limites de renderização de sprite. O NES só é capaz de exibir 64 blocos de sprite 8x8 na tela de uma vez, e apenas 8 blocos de sprite na mesma linha horizontal entre si. Quando esses números forem atingidos, qualquer outro bloco de sprite não será renderizado na tela. É por isso que muitos jogos do NES apresentavam sprites tremeluzentes quando havia muitos deles na tela ao mesmo tempo. Dessa forma, ele está exibindo apenas determinados sprites em quadros alternados. Esses limites são algo que os artistas precisam ter em mente quando estiverem sobrepondo sprites uns sobre os outros porque, embora dobrem o número de cores, também dobram o número de blocos de sprite na mesma linha horizontal.

As camadas de sprite também podem ser feitas com o plano de fundo para contornar os limites da tabela de atributos. Esse truque é geralmente usado para imagens estáticas, como telas de histórias e retratos de personagens, para dar a elas uma profundidade de cor muito maior. Para isso, o artista desenhava parte da imagem como plano de fundo e, em seguida, colocava sprites em camadas sobre ela para preencher o restante.

Para explicar a próxima grande restrição do NES, primeiro precisamos voltar ao fato de que os gráficos são armazenados em blocos. Os blocos gráficos são armazenados em 256 páginas de blocos, e os blocos dessas páginas não podem ser carregados na VRAM em locais diferentes, o que dificulta a mistura e a combinação de blocos de páginas diferentes em tempo real. A VRAM do NES só é capaz de exibir 512 desses blocos de uma vez. Além dessa restrição, ele divide os blocos ao meio para os sprites e o plano de fundo. Isso significa que ele só é capaz de exibir 256 blocos de sprite e 256 blocos de plano de fundo em um determinado momento. Isso pode se tornar muito restritivo se o artista quiser exibir uma grande variedade de sprites e elementos de fundo.

Para combater essa limitação, o NES tem um recurso que permite que o artista divida cada página em páginas parciais chamadas bancos. Portanto, embora o NES não seja capaz de carregar blocos individuais de vários pontos nos dados gráficos, ele é capaz de carregar diferentes seções de uma página em momentos diferentes. Na maioria dos jogos, esses bancos serão de 1K ou 2K. Um banco de 1K equivale a um quarto de uma página ou 64 blocos, enquanto um banco de 2K equivale à metade de uma página ou 128 blocos. O artista deve decidir se deseja reservar o uso de cada tipo de banco para Sprites ou elementos de plano de fundo, pois ambos os tipos de bancos precisam ser utilizados. Isso significa que você não pode ter bancos de 1K para os sprites e os planos de fundo. Uma página precisa usar bancos de 1K e a outra precisa usar 2K. De modo geral, a maioria dos jogos tende a usar bancos de 1K para os sprites e bancos de 2K para os planos de fundo, pois os conjuntos de blocos de plano de fundo tendem a ser mais estáticos e precisam de menos variedade em tempo real.

A utilidade dos bancos de 1K para sprites é bastante significativa. Se o sprite do jogador tiver uma grande variedade de animações que não cabem em uma única página, juntamente com todos os outros sprites que precisam ser carregados, as ações individuais podem ser salvas em bancos de 1K e, em seguida, trocadas entre si, dependendo da ação que estiver acontecendo na tela. Ele também permite uma variedade maior de sprites que podem ser usados em uma única área de um jogo. Por exemplo, se o jogador tiver que encontrar seis tipos diferentes de inimigos em uma área do jogo, mas a página de sprite só permitir o jogador e três outros tipos de sprites, quando um tipo de inimigo for eliminado da tela, o jogo poderá trocar um dos bancos de inimigos por um novo tipo de inimigo.
Uma das únicas grandes desvantagens de usar bancos de 1K para sprites e bancos de 2K para planos de fundo é a forma como o NES lida com a animação de plano de fundo. Para animar um elemento do plano de fundo de um jogo do NES, o artista precisa criar bancos duplicados dos elementos animados do plano de fundo. Cada novo banco duplicado conterá o próximo quadro de animação para cada um dos elementos animados. Esses bancos são então trocados um a um, como em um flip book, para criar a animação. Se o artista estiver usando bancos de meia página para os planos de fundo, o armazenamento de todos esses bancos duplicados poderá ocupar muito espaço. Uma maneira de contornar isso é colocar todos os elementos de fundo animados do jogo inteiro em um único banco. Porém, isso também deixa o artista com a restrição de ter apenas 128 blocos restantes para os elementos estáticos de cada plano de fundo. Cabe ao artista decidir o melhor curso de ação ao decidir quais tipos de bancos serão usados para a arte.
Muitos jogos dessa época empregam truques para criar efeitos como rolagem de paralaxe em segundo plano, mas esses também representam um desafio para os artistas e designers. Embora os consoles de 16 bits posteriores permitissem várias camadas de fundo, essa não é uma opção no NES. Todos os planos de fundo são uma única imagem achatada. Para criar uma sensação de profundidade e camadas, foram usados diferentes truques de programação. Para criar um plano de fundo de paralaxe, por exemplo, o desenvolvedor pode definir um registro que pode dizer quando uma determinada linha horizontal (conhecida como linha raster) está sendo renderizada na tela. Em seguida, eles podem usar esse registro para controlar a velocidade e a direção da rolagem da tela. Com isso, eles podem criar uma linha horizontal do plano de fundo que rola em uma velocidade diferente do restante do plano de fundo. O truque para os artistas e designers nesse ponto é ter em mente que o plano de fundo ainda é uma imagem plana. Se uma plataforma ou qualquer outro elemento que deveria estar "na frente" desse fundo de movimento mais lento for colocado nessa região, ele também será rolado mais lentamente do que o restante da imagem. Isso significa que os designers precisam estar atentos ao local onde estão colocando os elementos de fundo na cena, e os artistas precisam criar o fundo de forma que o efeito seja perfeito.

Há também outro truque para artistas que desejam que um de seus elementos de fundo apareça em primeiro plano. No NES, os desenvolvedores podem definir a prioridade de um sprite como sendo menor que zero. Quando isso for feito, o sprite será exibido atrás de qualquer pixel de fundo não transparente. As prioridades do sprite também podem ser modificadas e acionadas em tempo real, permitindo que determinados elementos alterem a prioridade de um sprite conforme necessário.
Quando alguém está tentando criar um projeto que seja autêntico para um console retrô, há muitas considerações técnicas que precisam ser levadas em conta e com as quais o desenvolvimento moderno talvez não precise se preocupar. Devido à maneira como as máquinas mais antigas renderizavam imagens e lidavam com o fato de terem pouco espaço para manobrar com a CPU e a GPU, os designers precisavam pensar de forma criativa para contornar as limitações do hardware. Na era moderna, é importante aprender sobre essas limitações e técnicas para realmente recriar o visual e o design dos jogos daquela época. Na próxima postagem, analisaremos as limitações de design impostas pela era dos 16 bits, bem como o trabalho do Unity necessário para obter a verdadeira sensação de "TV antiga". O guia 2D Pixel Perfect para visuais retrô de 16 bits já está disponível aqui.
---
Está criando níveis pela primeira vez com o Tilemap? Explore a construção de mundos em 2D neste tutorial para iniciantes no Unity Learn.