GameDev

Aprendendo a programar jogos em Unity: Prefabs, facilitando a manutenção e reutilização de objetos

Vamos utilizar uma importante funcionalidade do Unity que permite a transformação de GameObjects em assets reutilizáveis.

Seja bem-vindo(a) ao GameDev: Aprendendo a programar jogos em Unity de hoje! Prosseguindo com o processo de desenvolvimento de nosso primeiro platformer 2D, iremos aprender a utilizar uma importante ferramenta do Unity, que permitirá a reutilização de objetos, personagens e itens de uma fase em outra, ou mesmo em outro projeto, sem perder a rastreabilidade de suas características.


Caso seja a primeira vez que você acessa esta série, fique à vontade para juntar-se a nós em uma caminhada de muito aprendizado e desenvolvimento. A partir do primeiro tópico, você irá conhecer mais sobre como um game é criado utilizando Unity, a instalação da ferramenta em seu computador e os passos de desenvolvimento de um jogo, codificação e montagem das fases, personagens e desafios. 

Nossa série é elaborada de forma a permitir, por meio de exemplos e projetos, que você possa criar “do zero” os games que sempre sonhou em tirar do papel. No momento, estamos desenvolvendo Motorista da Pesada, um game cujo principal objetivo proposto ao jogador é a coleta, no menor tempo possível, de caixas de presente espalhadas pelas fases, utilizando-se para isso de um simpático carrinho, que irá percorrer diferentes caminhos, sempre tomando cuidado para não esbarrar em perigosas bombas.

No tópico anterior de nossa jornada, aprendemos mais sobre a funcionalidade de Raycast do Unity, que permitiu, em nosso game, a implementação de uma funcionalidade para restringir os pulos de nosso personagem principal pelos cenários apenas enquanto estiver posicionado sobre o chão ou plataformas flutuantes. Além disso, introduzimos à primeira fase algumas trilhas e efeitos sonoros, para aumentar a imersão do jogador na aventura que propomos. Venha conosco e vamos juntos nesta jornada rumo a novos conhecimentos!

Entre maçãs e jacas

Imagine, por um momento, que você foi requisitado para elaborar um novo e ambicioso jogo tridimensional, ambientado em uma grande fazenda virtual, com vastos plantios de macieiras.

Para esse hipotético jogo novo, você passou dias montando o layout dos cenários, posicionando objetos, árvores, frutos, grama, itens e outros elementos que o compõem. Criou diversas Scenes no Unity, representando diferentes partes dessa fazenda, sempre caprichando em cada uma delas, posicionando diversas macieiras carregadas de maçãs bem vermelhas.

Ao término dessa tão trabalhosa sequência de atividades, você descobre que, por um mal-entendido na comunicação com os idealizadores do enredo do game, na verdade o jogo deveria ter sido ambientado em uma enorme plantação... de jaqueiras!

Tentando recuperar o tempo perdido, você começa a modificar os GameObjects de cada árvore, pertencente a cada uma das cenas, perdendo preciosas horas ao trocar centenas de maçãs por jacas.

Modificações desse tipo, como trocar um sprite ou o texto de um mesmo objeto presente em diversas cenas, para jogos de porte pequeno, como Motorista da Pesada, não representam um problema tão grande, pois não costumam tomar muito tempo do desenvolvedor. Porém, para games cujo tamanho e complexidade aumentam consideravelmente conforme avança-se o desenvolvimento do projeto, seria um baita problema ter de efetuar alterações em centenas de objetos, presentes em dezenas de cenas diferentes.

Para evitar que o programador “enfie o pé na jaca” desse jeito, o Unity oferece uma funcionalidade muito útil chamada Prefab, que permite transformar um GameObject em um asset reutilizável, contemplando quase que a totalidade de suas características, tais como seu posicionamento, cor, sprite, modelo 3D, componentes e scripts atrelados ao objeto.

Como funciona um Prefab

Basicamente, ao se converter um GameObject em um Prefab, o Unity realiza duas ações:
  • Escreve, em um arquivo de extensão .prefab, as propriedades do objeto e de todos os componentes e scripts que estão atrelados a ele; e
  • Indica, na aba Hierarchy, que determinado GameObject da cena em questão deriva de um determinado Prefab.
Dessa forma, se realizarmos alterações diretamente no arquivo de um Prefab, essas alterações serão replicadas em todos os GameObject criados com base nele.

Em nosso exemplo “do mundo rural”, se as árvores da vasta plantação virtual de maçãs fossem criadas a partir de um Prefab, bastaria alterar as propriedades de seu arquivo diretamente no Unity para que todas as macieiras de todas as cenas “se tornassem” jaqueiras sem tanto esforço.

É importante ressaltar, também, que o Unity permite, caso necessário, alterar características de um GameObject derivado de um Prefab sem influenciar os demais. Dessa forma, há flexibilidade suficiente para agilizar o trabalho do programador, permitindo ampla reutilização de objetos sem prejudicar eventuais necessidades pontuais.

Implementando Prefabs no projeto

Agora que já conhecemos os pormenores de tão importante funcionalidade do Unity, que tal colocarmos a mão na massa em nosso projeto e criarmos alguns Prefabs, baseados em objetos que já inserimos e codificamos em nossa primeira fase?

Para isso, abra o Unity Hub e clique duas vezes sobre o item referente ao projeto Motorista da Pesada. Na interface inicial do Unity, na aba Project, abra a pasta Assets, Scenes e, por fim, clique duas vezes no ícone da cena Fase01.

Para organizarmos melhor os arquivos que serão gerados ao se transformar alguns GameObjects em Prefabs, vamos criar uma nova pasta. Na aba Project, clique duas vezes sobre a pasta Assets e, após, clique com o botão direito sobre alguma área vazia da janela que apresenta o conteúdo da pasta em questão. No menu suspenso, clique em Create e, em seguida, Folder, conforme exemplo a seguir:

O nome de nossa nova pasta será “Prefabs”, sem as aspas. Clique duas vezes sobre seu ícone para abrir a nova pasta vazia.

O primeiro GameObject que iremos converter em Prefab será o botão de pause da fase. Para realizar essa conversão, basta clicar e arrastar o item do GameObject BotaoPause (subordinado ao objeto CanvasFase), da lista da aba Hierarchy, em direção à área da pasta aberta (Prefabs) na aba Project, conforme a ilustração a seguir melhor apresenta:

Após a realização dessa ação, note que um novo arquivo será apresentado. Trata-se do Prefab BotaoPause, representado pela ilustração de um cubo na cor azul.


Clique uma vez sobre seu ícone e note que, na aba Inspector, são apresentadas características sobre os componentes do Prefab em questão:


Observe também algo muito interessante: na aba Hierarchy, o GameObject que utilizamos de base para criarmos o Prefab BotaoPause agora também está com sua representação gráfica na cor azul. Isso indica que o objeto em questão deriva de um Prefab.


Agora, iremos editar o Prefab para percebermos que as alterações realizadas nele irão ser replicadas no objeto que está presente na cena Fase01. Para tal, na aba Project, clique duas vezes sobre o ícone do Prefab BotaoPause.

É possível notar que, momentaneamente, não estamos mais editando os elementos de Fase01 ao se observar as abas Hierarchy e, também, o conteúdo das abas Scene e Inspector, que mostram apenas informações sobre o Prefab em questão.

Vamos alterar a cor do botão. Para isso, na aba Hierarchy, selecione BotaoPause e, na aba Inspector, altere os parâmetros de Color do componente Image para R = 160, G = 255, B = 180 e A = 255, conforme exemplo a seguir:


Feito isso, clique na seta em destaque da imagem a seguir, presente na aba Hierarchy ao lado esquerdo do nome do Prefab:

Voltamos à cena que estávamos editando anteriormente. Observe que, agora, nosso botão de pause, assim como seu Prefab de origem, está colorido em tons de verde claro.

Objetos subordinados

Agora que já experimentamos criar um Prefab a partir do objeto referente ao botão de pause da fase, crie também novos Prefabs baseados nos seguintes objetos, todos subordinados ao GameObject CanvasFase:
  • Cronometro;
  • ItensRestantes;
  • ContadorVidas;
  • TelaPause;
  • TelaGanhou; e
  • TelaPerdeu.
A pasta Prefabs e a aba Hierarchy ficarão como o representado na imagem a seguir:

Vamos editar, agora, o Prefab de nome TelaPerdeu, clicando duas vezes sobre seu respectivo ícone. Ao se realizar tal ação, veja que, na aba Scene, nada será exibido:

Isso deve-se ao fato de que, ao realizarmos a conversão do GameObject para Prefab, pelo objeto estar desativado naquele momento, essa característica também é replicada no Prefab, conforme indicado no exemplo a seguir.

Para editarmos adequadamente o Prefab, na aba Hierarchy, selecione TelaPerdeu e, na aba Inspector, ative momentaneamente o objeto, clicando sobre a caixa de seleção destacada em verde, na imagem a seguir.

Algo muito interessante é o fato de que os objetos subordinados a TelaPerdeu também foram adequadamente encapsulados dentro da estrutura do Prefab criado. Portanto, poderemos alterar suas características e essas alterações serão replicadas, também, para os respectivos GameObjects nas cenas do jogo.

Na aba Hierarchy, selecione o objeto Sair. Na aba Inspector, troque o texto de seu componente Text para “Voltar ao menu inicial”, sem as aspas, e o parâmetro Width de seu componente Rect Transform para 500.

Como originalmente essa tela não é exibida até se perder a partida, na aba Hierarchy devemos selecionar novamente TelaPerdeu e, em seguida, desativar o objeto, clicando novamente na caixa de seleção da aba Inspector destacada em verde, na imagem a seguir.

Por fim, clique na seta em destaque da imagem a seguir, presente na aba Hierarchy ao lado esquerdo do nome do Prefab, e voltaremos à cena de nosso jogo.


Para confirmar se houve a devida alteração, experimente ativar temporariamente o GameObject TelaPerdeu de Fase01 para dar uma olhada, não se esquecendo de desativá-lo novamente, após dar a conferida.

Sobrescrevendo propriedades de um Prefab

Conforme informado anteriormente, existe a possibilidade de, para um GameObject em específico de uma fase derivado de um Prefab, trocar algum parâmetro de seus componentes sem prejudicar os demais objetos derivados.

Vamos experimentar realizar esse tipo de alteração, utilizando como exemplo novamente o botão de pause de nossa fase. Para isso, na aba Hierarchy, selecione o GameObject BotaoPause, subordinado a CanvasFase

Modifique os parâmetros de Color de seu componente Image para a cor branca (R, G, B e A = 255), assim como era o botão antes de sua conversão em um Prefab.

No editor do Unity, toda propriedade dos componentes de um GameObject derivado de um Prefab cujo valor foi sobrescrito, em relação ao valor padrão do Prefab, apresenta uma pequena indicação visual na tela: letras em negrito e, para algumas propriedades, um pequeno sinal visual em azul, conforme destacado no exemplo a seguir:


Caso o programador queira desfazer as alterações, voltando ao valor padrão do Prefab para a propriedade em questão, basta clicar com o botão direito sobre a propriedade e selecionar a opção Revert; já se o programador quiser aplicar a alteração em questão para o Prefab em si, tornando o valor alterado o novo padrão, selecionará a opção Apply to Prefab.

Em nosso caso, para o parâmetro Color do componente Image de BotaoPause, iremos selecionar a opção Revert, deixando-o novamente em tons esverdeados, seguindo o padrão de nosso Prefab.

Prefabs de outros elementos

Até o momento, realizamos a conversão para Prefab apenas de elementos de nossa primeira fase subordinados ao GameObject CanvasFase. Iremos, agora, começar a converter outros objetos, subordinados ao Cenario e a seus filhos.

Comece convertendo o GameObject Personagem, clicando e arrastando seu elemento, da aba Hierarchy para uma área vazia dentro da pasta Prefabs, da aba Project.

Observe que, diferentemente dos outros Prefabs, a representação gráfica (ícone) do elemento recém-convertido não é um cubo em tons azuis, mas sim a imagem do sprite do objeto, representando de forma mais fiel a qual tipo de elemento do jogo tal Prefab corresponde. Isso é possível quando trata-se de um objeto com um componente do tipo Renderer atrelado — no caso de Personagem, um Sprite Renderer.

Outros potenciais GameObjects a serem convertidos são os nossos coletáveis e nossas bombinhas, mas não iremos convertê-los nesse momento devido a uma peculiaridade de nosso projeto relativo aos elementos explosivos de nossa fase.

Até o momento, as bombinhas espalhadas pela fase são representadas pelo desenho simples de um explosivo com o pavio aceso, conforme exemplo a seguir:

Porém, temos à disposição três sprites de bomba que, se apresentados sequencialmente, podem dar um efeito bacana de “bomba prestes a explodir” aos nossos elementos, semelhante ao efeito de animação utilizado em games como Bomberman.

Dessa forma, será mais adequado realizarmos a implementação dessa animação antes de transformarmos os objetos em Prefabs.

Salve a cena (menu File, Save) e o projeto (menu File, Save Project) antes de fechar o Unity.

Próximos passos

Hoje conhecemos mais sobre os Prefabs e os potenciais ganhos que seu uso pode trazer a um projeto de desenvolvimento de um jogo, por exemplo, em relação a propriedades compartilhadas entre mais de um GameObject, mesmo que estejam em cenas diferentes. De fato, os Prefabs facilitam bastante os processos de reaproveitamento de objetos, realização de manutenções e alterações de parâmetros de componentes e objetos de um game.

Em nosso próximo encontro vamos conhecer alguns elementos do Unity que facilitam a elaboração e aplicação de animações em objetos bidimensionais, como por exemplo nossas bombinhas, que ficarão bem “animadas” com os sprites do projeto que foram reservados para tal finalidade.

Nosso próximo texto já encontra-se disponível, continue conosco nessa jornada de conhecimento e fique ligado sempre aqui no GameBlast!

Revisão: Ives Boitano

Entendo videogames como sendo uma expressão de arte e lazer e, também, como uma impactante ferramenta de educação. No momento, doutorando em Sistemas da Informação pela EACH-USP, desenvolvendo jogos e sistemas desde 2020. Se quiser bater um papo comigo, nas redes sociais procure por @RodrigoGPontes.
Este texto não representa a opinião do GameBlast. Somos uma comunidade de gamers aberta às visões e experiências de cada autor. Escrevemos sob a licença Creative Commons BY-SA 3.0 - você pode usar e compartilhar este conteúdo desde que credite o autor e veículo original.


Disqus
Facebook
Google