GameDev

Aprendendo a programar jogos em Unity: começando a trabalhar com elementos de física

Vamos finalizar a implementação das plataformas e começar a criar itens e scripts que envolvam aspectos de física dos objetos.

em 02/11/2023
Seja bem-vindo(a) ao GameDev: Aprendendo a programar jogos em Unity de hoje! Dando continuidade ao processo de criação de nosso primeiro platformer 2D, iremos concluir a construção das plataformas e do chão da fase inicial, e começar a introduzir conceitos de física para o personagem e o ambiente.


Caso seja a primeira vez que você acessa nossa série, convido-lhe a acompanhar todo o conteúdo que foi desenvolvido até agora. A partir de nosso primeiro tópico você irá aprender desde a instalação e configuração da ferramenta Unity até a concepção, codificação e criação de um ou mais games a partir do zero, por meio dos diversos projetos que estamos propondo.

No momento estamos desenvolvendo nosso segundo jogo, cujo nome é Motorista da Pesada e, no tópico anterior de nossa jornada, aprendemos a utilizar a ferramenta Sprite Editor por meio da inserção de plataformas flutuantes na cena de nossa primeira fase. Venha conosco e vamos juntos nesta trilha rumo a novos conhecimentos!

Um chão sob nossos pés (ou rodas)

Até o nosso último encontro foram criados com êxito diversos elementos na cena de nossa primeira fase, como o fundo do cenário, o personagem (carrinho) e plataformas flutuantes. Mas é importante termos um chão no cenário, e para isso iremos utilizar os conhecimentos que adquirimos até agora em conjunto com novas funcionalidades importantes.

Vamos retomar o desenvolvimento do projeto, abrindo o Unity Hub e clicando 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.

Subordinados ao GameObject Itens, criamos há algum tempo dois objetos que, além de seus “vizinhos” que representam as plataformas, são referentes à composição do chão em nossa primeira fase: trata-se de Chao01 e Chao02, indicados em destaque na imagem a seguir:


Para eles, iremos utilizar outro modelo de sprite, diferente do adotado para as plataformas flutuantes. Então, na aba Project, vamos clicar duas vezes sobre o ícone da pasta Assets, em seguida Multimidia e, por fim, Imagens, para que possamos selecionar o elemento de nome “plataformas_C”, conforme indicação a seguir:

Assim como o arquivo de imagem com o qual interagimos em nosso último tópico, este também é uma imagem que contempla múltiplos sprites em um “pacote” só e, portanto, deverá ter as coordenadas ajustadas por meio do Sprite Editor.

Com a imagem selecionada, na aba Inspector clique no botão Sprite Editor:

Assim que a imagem for apresentada na janela da ferramenta, iremos clicar sobre o menu Slice (destacado em verde na imagem a seguir), ajustar os parâmetros pelo indicado pelas setas da imagem e, por fim, na opção Slice (destacado em amarelo):

Feito isso, clique na representação gráfica da primeira plataforma (acima), cujo nome designado pelo Unity foi “plataformas_C_0”.

Ajuste os parâmetros border do elemento com os valores L = 50 e R = 57. Para realizar essa alteração, basta clicar e arrastar os quadradinhos laterais circulados em verde da imagem a seguir em sentido ao centro da imagem, ou digitar diretamente os valores nas caixas de texto destacadas em vermelho. Por fim, clique em Apply.

Essa última operação que realizamos vai servir para que, mesmo que um objeto tenha dimensões horizontalmente bem grandes, como será o caso de nossos objetos Chao01 e Chao02, não haja uma distorção da imagem, sendo o conteúdo central repetido até cobrir toda a extensão da imagem.

Veja, no exemplo a seguir, a comparação entre um objeto que adota essa técnica (na imagem a seguir, a representação de cima) em comparação com outro em que a imagem-base é apenas esticada.

A primeira imagem fica bem mais natural, em relação à apresentação, do que imagem esticada, não concorda?

Agora iremos fechar a janela da ferramenta Sprite Editor e, ainda com a imagem selecionada, na aba Inspector iremos modificar os dois parâmetros destacados em vermelho para os valores apresentados na imagem (Mesh Type = Full Rect e Wrap Mode = Repeat), clicando em Apply após as alterações realizadas.

Esses dois ajustes têm como finalidade, no caso do Mesh Type, indicar que o sprite em questão é um retângulo “inteiro” (para fins de cálculos internos da ferramenta) e, em relação ao Wrap Mode, garantir que, em determinados modos de utilização do sprite, ele seja repetido indefinidamente e não “esticado” ou outro comportamento não desejado.

Agora, finalmente, iremos introduzir o sprite na representação visual dos GameObjects Chao01 e Chao02. Para tal, na aba Hierarchy,  iremos selecionar os dois GameObjects citados e, na aba Inspector, iremos alterar o parâmetro Sprite do componente Sprite Renderer de ambos os objetos para o item de nome “plataformas_C_0”. Além disso, iremos alterar o parâmetro Size Width para o valor 25 e Size Height para o valor 1, conforme indicado pela imagem a seguir:

Feita a introdução do sprite nos objetos, vamos posicioná-los adequadamente no cenário. Selecione apenas Chao01 e altere os valores dos parâmetros X e Y de seu componente Transform para -23 e -2.5, respectivamente. Também iremos alterar os valores de Chao02, mas desta vez os parâmetros X e Y de seu componente Transform receberão os valores 0 e -2.5, respectivamente.


Olha que legal o que a imagem a seguir representa: um chão, composto de dois elementos, cuja imagem não está esticada, mas repetindo o padrão interno do sprite utilizado!

Agora, assim como fizemos anteriormente com as plataformas, selecione os dois objetos referentes ao chão e, na aba Inspector, acrescente a ambos o componente Mov Fundo (botão Add Component, Scripts, Mov Fundo). O valor do parâmetro Velocidade será 0.2, de Limite Min será -23 e de Limite Max será 22, conforme exemplo a seguir:

Experimente ver o deslocamento funcionando indo à aba Game e clicando no botão Play. Ao final da experimentação, não se esqueça de interrompê-la, clicando novamente no botão Play e retornando à aba Scene.

Gravidade em ação

Já temos fundo, plataformas e um belo chão, mas até agora nosso querido carrinho está somente “flutuando” pelo ambiente. Chegou a hora de inserirmos elementos ao nosso personagem para que ele possa, de fato, percorrer os caminhos sobre o chão, assim como um veículo de verdade.

Utilizaremos a partir de agora alguns elementos e scripts que, aproveitando todo o “poder” computacional que nos é oferecido pelas diversas ferramentas da engine Unity, simulam aspectos da vida real importantes em um platform, como a gravidade, por exemplo. 

Na aba Hierarchy, selecione o GameObject Personagem. Na aba Inspector, clique no botão Add Component, opção Physics 2D e, por fim, no item Rigidbody 2D. Será inserido um componente como o representado na imagem a seguir:

Os componentes Rigidbody e Rigidbody 2D são responsáveis por conceder propriedades físicas a um objeto 3D ou 2D da cena do jogo, respectivamente. Ambos apresentam diversos atributos com correspondência a fatores que, na vida real, impactam na interação física entre corpos, como Mass (representando a massa do objeto), Drag (Linear e Angular, ambas representando fatores que influenciam arraste e atrito) e Gravity scale (representando a multiplicação do fator gravitacional sobre o objeto).

Com tantos atributos assim, que tal experimentar e ver o que acontece com nosso objeto a partir da inserção desse elemento? Vá à aba Game e pressione Play para vê-lo em ação:

Pois é, de fato a gravidade está “ligada”, mas parece que nosso carrinho foi fundo demais… Precisamos ajustar alguns elementos tanto no carrinho quanto nos outros elementos da cena para que as coisas andem conforme o planejado.

Primeiro, iremos acrescentar ao objeto Personagem um componente do tipo Box Collider 2D (botão Add Component, Physics 2D):

Verifique se os parâmetros do componente, em especial os do campo Size, estão conforme o exemplo a seguir; caso não estejam, altere-os para o indicado (parâmetros Offset = 0, Size X = 2.88 e Size Y = 1.47).


Agora, na aba Hierarchy, selecione os dois GameObjects referentes ao chão do cenário. Na aba Inspector, acrescente elementos Box Collider 2D aos objetos e modifique os parâmetros Size X e Y de ambos para 25 e 1, respectivamente. Isso é necessário para que a área de alcance do Box Collider 2D cubra toda a área que os sprites estão utilizando (lembre-se de que, anteriormente, demos o valor 25 para o Size Width de cada Sprite Renderer).

Vamos experimentar agora a execução do game para ver se a antiga expressão popular “se cair, do chão não passa” agora é válida para o nosso jogo:

Parece que agora está tudo em ordem com o chão, que bom! Interrompa a simulação do game para darmos prosseguimento à inserção do mesmo componente para outros elementos de nossa primeira fase.

A propósito, talvez você esteja se perguntando sobre o porquê de não inserirmos o elemento Rigidbody 2D também para o chão. Isso deve-se ao fato de que o uso de Rigidbody 2D é adotado para objetos bidimensionais que sofrerão ação da gravidade e de impactos com outros objetos; no caso do chão e das plataformas, isso não é desejado, pois o comportamento que esperamos é de que elas permaneçam “suspensas” nas posições verticais que determinamos, não sendo necessária a ação da gravidade ou de outras forças que podem fazer elas “caírem”. Por isso, para elas apenas utilizaremos os componentes que provêm colisões.

Dadas as explicações, vamos selecionar agora todos os objetos referentes às plataformas; na aba Inspector, acrescente a eles componentes do tipo Box Collider 2D

Em determinados casos, o Unity calcula automaticamente as dimensões dos Box Colliders dos objetos com base em suas dimensões. Verifique se os parâmetros Size X e Y estão de acordo com a listagem a seguir, alterando-os caso não estejam iguais ao descrito:
  • Plataforma01: Size X = 4.2, Size Y = 1.2;
  • Plataforma02: Size X = 5.64, Size Y = 1.2;
  • Plataforma03: Size X = 5.64, Size Y = 1.2;
  • Plataforma04: Size X = 7.92, Size Y = 1.2; e
  • Plataforma05: Size X = 7.92, Size Y = 1.2.
Para fins de experimentação, selecione o objeto Personagem e, temporariamente, modifique os parâmetros Position X e Y de seu componente Transform para -5 e 2, respectivamente.

Agora experimente a execução do jogo, indo à aba Game e clicando no botão Play:

Viu que interessante é o comportamento do carrinho ao ser deslocado pelo cenário? O uso dos recursos de física do Unity deixa o movimento dos elementos mais parecidos com a realidade do que apenas transformando via script os parâmetros do componente Transform de um personagem. E por falar em script...

Vamos pular!

Interrompa a execução da simulação do game, volte à aba Scene e devolva os valores originais de X e Y do componente Transform referente ao GameObject Personagem.

Agora, na aba Project clique duas vezes no ícone referente à pasta Assets e, depois, em Scripts. Clique com o botão direito em alguma área da pasta e, no menu apresentado, clique na opção Create, C# Script. O nome de nosso novo script será Pulo, conforme ilustração a seguir:

Como o nome já indica, o comportamento atrelado a esse script será o de permitir que determinado objeto “pule” ao se acionar determinado comando; em nosso caso específico, o pressionamento da tecla barra de espaço.

Clique duas vezes sobre o ícone do novo script criado, para que ele possa ser aberto pelo Visual Studio.
Substitua o conteúdo que está presente dentro dos colchetes (a partir da linha 6 do arquivo) para o descrito a seguir:

    public float forca;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Vector2 sentidoCima = new Vector2(0, 1);
            gameObject.GetComponent<Rigidbody2D>().AddForce(sentidoCima * forca);
        }
    }

Nosso script será responsável por, assim que detectar o pressionamento da tecla barra de espaço (Input.GetKeyDown(KeyCode.Space)), aplicar uma força para cima no elemento Rigidbody2D do objeto ao qual esse script estiver atrelado, por meio da função AddForce.

A força aplicada irá depender do sentido indicado (sentidoCima, um vetor com valor Y = 1, ou seja, apontando para cima) e da intensidade desejada (variável pública forca, que iremos determinar daqui a pouco).

Existem diversos tipos de força que podem ser aplicados, como impulso, aceleração, dentre outros. Por enquanto iremos utilizar os parâmetros padrão, mas poderemos utilizar suas variantes nos próximos projetos.

Salve o script e minimize o Visual Studio para voltarmos à interface do Unity. Selecione o objeto Personagem e, na aba Inspector, clique no botão Add Component, Scripts e, por fim, em Pulo. Insira 400 no campo correspondente ao parâmetro Forca, conforme indicado pela imagem a seguir:

Agora vá à aba Game e pressione Play para ver o jogo em ação. Utilize as setas para se movimentar e a barra de espaço para pular:

Veja que, agora, o “núcleo” de movimentação e comportamento do personagem em nosso game está quase completo! É uma ótima notícia, mas ainda teremos que corrigir alguns aspectos da movimentação, pois, em determinados momentos, algumas coisas “estranhas” podem ocorrer:

Finalize a simulação da execução, pressionando novamente o botão Play. Não se esqueça de salvar a cena (menu File, Save) e o projeto (menu File, Save Project) antes de fechar o Unity.

Próximos passos

Como está ficando promissor nosso primeiro platformer 2D, não é mesmo? Primeiramente, lhe parabenizo por chegar até esta etapa, pois tenho certeza de que, conforme estamos avançando com o desenvolvimento de nossos projetos, também estamos aprendendo novos e importantes conhecimentos que poderão ser aplicados posteriormente no desenvolvimento de seus próprios projetos.

Em nossos próximos tópicos iremos adequar alguns aspectos da movimentação do personagem, a fim de deixá-la mais interessante e divertida ao jogador, além de iniciar o processo de inserção dos elementos coletáveis das fases.

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.