GameDev

Aprendendo a programar jogos em Unity: finalizando a construção da primeira fase do game

Vamos concluir a elaboração, o posicionamento e a formatação dos elementos que compõem o primeiro estágio de nosso jogo.

em 02/02/2024
Seja bem-vindo(a) ao GameDev: Aprendendo a programar jogos em Unity de hoje! Dando sequência ao processo de criação de nosso primeiro platformer 2D, iremos concluir o desenvolvimento da primeira fase do game, programando a execução dos diversos efeitos sonoros que serão executados em momentos específicos da jogatina, como ao se coletar um item ou ao concluir um estágio.


Caso esta seja a primeira vez que você acessa nossa série, não se acanhe e venha conosco nesta rica caminhada de aprendizado! Juntos, aprenderemos muito sobre o processo de desenvolvimento de jogos utilizando a ferramenta Unity: a partir do primeiro tópico, você terá acesso a conhecimentos práticos que te auxiliarão no processo de criação dos jogos que sempre sonhou em tirar do papel, desde a instalação da ferramenta até os processos de programação e construção de cenas, objetos e fases. Dessa forma, posteriormente, você estará apto a desenvolver jogos de diversos estilos e gêneros.

No momento, estamos elaborando o platformer 2D Motorista da Pesada, um jogo em que o desafio é coletar, no menor tempo possível, caixas de presente espalhadas pelos cenários. Para isso, o jogador deverá guiar um simpático carrinho por diversos caminhos posicionados pelas fases. Além de ter de tomar cuidado com o tempo restante, o gamer deve ficar de olho em perigosas bombas espalhadas pelos cenários: encostando em três delas, é game over na certa!

No tópico anterior de nossa jornada prosseguimos no aprendizado sobre as ferramentas de animação que o Unity oferece ao desenvolvedor. Criamos uma animação para as caixas de presente coletáveis, interagindo com parâmetros de rotação de seus respectivos Transforms, além de aprendermos mais sobre o funcionamento dos Animation Controllers. Venha conosco e vamos juntos nesta jornada rumo a novos conhecimentos!

Caixas animadas

Agora que nosso objeto Coletavel01 está plenamente animado, vamos aplicar o que desenvolvemos em nosso último encontro para todas as caixinhas coletáveis de nosso cenário. Para isso, assim como fizemos anteriormente com as bombas, iremos converter nosso GameObject em um prefab.

Vamos começar a realizar alterações em nosso projeto dentro do editor. 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.

Ainda na aba Project, clique duas vezes sobre o ícone da pasta Assets e, em seguida, abra a subpasta Prefabs. Na aba Hierarchy, selecione o GameObject Coletavel01, subordinado a Itens, clique sobre seu ícone e arraste o elemento em direção a uma área vazia da pasta Prefabs, como no exemplo indicado a seguir. 

Um prefab de nome “Coletavel01” será criado. Assim como o prefab Bombinha01, o prefab recém-convertido mostrará, na aba Project, a ilustração que lhe é correspondente — neste caso, a imagem da caixinha de presentes. Além disso, o ícone do GameObject Coletavel01 na aba Hierarchy se tornará azul, conforme a ilustração a seguir indica:


Agora, iremos substituir os outros itens coletáveis da aba Hierarchy por versões baseadas no novo prefab. Como o GameObject Coletavel01 descende de um prefab, não há problemas em “cloná-lo”, pois os novos objetos manterão referência ao prefab. Dessa forma, na aba Hierarchy, clique com o botão direito sobre o objeto Coletavel01 e, no menu suspenso, selecione a opção Duplicate.

Um novo objeto de nome “Coletavel01 (1)” será criado. Repita a operação por mais cinco vezes, criando, por fim, seis cópias de Coletavel01, conforme indicado a seguir:


Como todos os objetos foram duplicados de Coletavel01, a princípio, todos mantêm o mesmo posicionamento na cena (parâmetros de Transform) do GameObject original. Devemos, então, copiar o posicionamento dos objetos coletáveis “sem animação” para os novos objetos criados, a fim de posicioná-los nos locais corretos.

Na aba Hierarchy, selecione o GameObject Coletavel02. Na aba Inspector, clique com o botão direito sobre o nome da aba Transform e, no menu suspenso apresentado, selecione a opção Copy Component.

Selecione agora o objeto Coletavel01 (1), clique com o botão direito sobre ele e escolha a opção Paste Component Values. Desta forma, estaremos trazendo todos os parâmetros (valores) do Transform de Coletavel02 para o objeto animado.

Repita as mesmas ações (copiar os valores do componente Transform de um GameObject para outro) para os objetos listados a seguir:
  • De Coletavel03 para Coletavel01 (2);
  • De Coletavel04 para Coletavel01 (3);
  • De Coletavel05 para Coletavel01 (4);
  • De Coletavel06 para Coletavel01 (5); e
  • De Coletavel07 para Coletavel01 (6).
Agora que os novos objetos animados estão posicionados, podemos excluir os coletáveis antigos. Selecione os GameObjects entre Coletavel02 e Coletavel07, clique com o botão direito sobre a seleção e escolha a opção Delete:


Para manter a nomenclatura “original” de nossos itens, renomeie os GameObjects a seguir para os nomes indicados, clicando sobre cada um dos seus itens na aba Hierarchy e escolhendo a opção Rename:
  • De Coletavel01 (2) para Coletavel03;
  • De Coletavel01 (3) para Coletavel04;
  • De Coletavel01 (4) para Coletavel05;
  • De Coletavel01 (5) para Coletavel06; e
  • De Coletavel01 (6) para Coletavel07.
Por fim, teremos todos os objetos derivando do prefab que criamos há pouco, posicionados corretamente no cenário.

Embora agora tenhamos diversas caixinhas de presente animadas pelo cenário, a aparência delas se tornou, de certa forma, monótona, pois todas estão reproduzindo o padrão de cores do sprite de Coletavel01, diferentemente  da variedade de cores que tínhamos antes.

Dessa forma, caso deseje, selecione alguns dos novos coletáveis criados e altere o parâmetro Sprite de seus componentes do tipo Sprite Renderers para alguns dos outros sprites que representam caixinhas de presente à disposição no projeto.

Ganhando um ponto

Para finalizarmos a construção da nossa primeira fase, vamos adicionar os efeitos sonoros que serão executados ao se realizar determinadas ações. O primeiro a ser codificado será o efeito sonoro de conquista de ponto, que será executado ao se coletar uma caixa de presente na fase.

Como já temos um script que faz o controle das ações relativas aos nossos objetos coletáveis, vamos editá-lo para adicionar ao seu código essa ação em específico. Na aba Project, abra a pasta Assets e, em seguida, Scripts. Clique duas vezes sobre o ícone do script Itens para realizarmos sua edição no Visual Studio.

Iremos inserir, logo após a linha de código em que se registra um ponto ganho (Partida.PontosJogador++;), o seguinte trecho de código:
    GameObject.FindGameObjectWithTag("AudioPontoGanho").GetComponent<AudioSource>().Play();

Esse código será responsável por localizar, dentre os GameObjects ativos da cena, um objeto que esteja com a tag de nome “AudioPontoGanho” atrelada. Após a localização, ele irá acionar a função Play() de seu componente do tipo AudioSource.

Como ainda não temos esse objeto criado, muito menos a tag AudioPontoGanho, vamos salvar o script e voltarmos ao editor, minimizando o Visual Studio, para realizarmos as duas ações.

Na aba Hierarchy, clique com o botão direito sobre Fase01 e, no menu suspenso, selecione GameObject, Audio e, em seguida, a opção Audio Source. Essa ação criará um novo objeto já com o componente Audio Source atrelado a si.

Em encontros anteriores, realizamos ações bem parecidas para criar novos GameObjects, mas clicando com o botão direito sobre um “espaço vazio” da aba Hierarchy. Como já criamos muitos objetos em nossa cena, é provável que tenhamos poucos espaços vazios para clicar na referida aba do editor. Portanto, trata-se de uma forma ligeiramente diferente de concretizarmos a mesma ação.

Renomeie o GameObject recém criado para “AudioPegouItem”, sem as aspas. Selecione o objeto e, em sua aba Inspector, clique sobre a caixa de seleção de tags e, em seguida, clique na opção Add Tag…, conforme ilustrado a seguir:

Vamos criar três novas tags. A primeira receberá o nome “AudioPontoGanho”, sem as aspas, para que o código que implementamos agora há pouco funcione corretamente. As demais deverão ser criadas com os nomes “AudioVitoria” e “AudioDerrota”.


Voltaremos a selecionar, na aba Hierarchy, o objeto AudioPegouItem. Na aba Inspector, clique sobre a caixa de seleção de tags e selecione a tag recém-criada AudioPontoGanho.

Modifique o parâmetro AudioClip do componente Audio Source para o som de nome “moedinha”. Modifique, também, o parâmetro Play On Awake, deixando-o com sua caixa de seleção vazia, conforme ilustrado a seguir.


Experimente ver (e ouvir) como seu jogo está ficando, indo à aba Game e pressionando o botão Play. Ajuste o volume do efeito sonoro a gosto, mas lembre-se de que ajustes realizados durante a simulação de execução não são salvos, portanto aproveite a simulação para testar os níveis do volume e, após interromper a simulação, modifique o valor do mesmo em “definitivo”.

Sons de vitória e de derrota

Após voltar da simulação da execução, vamos abrir no Visual Studio novamente nosso script Itens, pois iremos editá-lo para programarmos o som que será executado ao se vencer uma fase em nosso jogo. 

Dentro da estrutura condicional em que são realizadas ações relacionadas ao momento da vitória na fase, logo após a linha de código em que é ativado o objeto telaGanhou (Partida.atualControladorFase.telaGanhou.SetActive(true);), insira o seguinte trecho de código:
    GameObject.FindGameObjectWithTag("AudioVitoria").GetComponent<AudioSource>().Play();

O código será responsável por ação semelhante ao executado ao se coletar uma caixa de presentes, porém, neste caso, irá procurar o objeto com a tag AudioGanhou atrelada a si antes de ordenar a execução de seu áudio.

Salve o script e minimize o Visual Studio. No editor do Unity, com a aba Project ainda exibindo a pasta Scripts em aberto, clique duas vezes sobre o ícone do script ControladorFase. Iremos editá-lo pois, em determinado trecho de seu código, são realizadas as ações relacionadas ao momento em que se é derrotado.

No Visual Studio, vamos editar o trecho de código referente à função Perdeu(). Logo após a linha em que é realizada a ativação da tela de derrota (telaPerdeu.SetActive(true);), insira o seguinte trecho de código:
    GameObject.FindGameObjectWithTag("AudioDerrota").GetComponent<AudioSource>().Play();

Semelhantemente ao que fizemos anteriormente, o objeto com a tag AudioDerrota atrelado a si terá o áudio de seu componente Audio Source executado.

Salve o script e minimize o Visual Studio. No editor, iremos criar agora dois GameObjects com componentes Audio Source atrelados. Repita a mesma ação que realizamos para criar o objeto AudioPegouItem (aba Hierarchy, botão direito sobre Fase01, menu GameObject, Audio, opção Audio Source) por duas vezes, nomeando os objetos como “AudioGanhou” e “AudioPerdeu”.


Na aba Hierarchy, selecione o objeto AudioGanhou e, na aba Inspector, atrele ao objeto a tag AudioVitoria. O parâmetro AudioClip de seu componente Audio Source será o som de nome “somVitoria” e Play On Awake deverá ficar com sua caixa de seleção vazia.

Já o objeto AudioPerdeu deverá ter a tag AudioDerrota atrelada a si. O parâmetro AudioClip de seu componente Audio Source será o som de nome “somDerrota” e Play On Awake também deverá estar com sua caixa de seleção vazia.

Com a criação dos dois objetos e os respectivos atrelamentos de suas tags, os códigos que criamos poderão “alcançar” os objetos e realizar a execução dos efeitos sonoros nos momentos adequados.

Experimente agora simular a execução do jogo. Teste a coleta de todas as caixas de presente, para verificar o comportamento em caso de vitória. Além disso, simule as condições de derrota do jogo, encostando em muitas bombas para perder as vidas e, também, pelo estouro do limite de tempo da partida.

Não se esqueça de, após interromper a simulação, salvar a cena (menu File, Save) e o projeto (menu File, Save Project) antes de fechar o Unity.

Próximos passos

Finalmente concluímos nossa primeira fase! Foi um processo relativamente longo, mas de muitos aprendizados, que, com certeza, irão nos auxiliar daqui em diante.

Pudemos conhecer mais sobre diversos aspectos da construção de uma fase na elaboração de um platformer 2D e, agora, estamos aptos a construir as próximas etapas deste game “da pesada”. Parabéns pela perseverança e pelos resultados alcançados.

Em nosso próximo encontro iremos dar início à elaboração da segunda fase do game, reaproveitando muito do que já criamos como estrutura-base para a primeira parte desta aventura. Estamos quase lá! Em pouco tempo, teremos nosso projeto completo e o jogo plenamente funcional.

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.