Unity

Desenvolvendo seu primeiro jogo com Unity e C#, Parte 2

Adam Tuliper

Baixar o código de exemplo

Bem-vindo mais uma vez a minha série sobre o Unity. No primeiro artigo, eu abordei alguns conceitos básicos e arquitetura do Unity. Neste artigo, vou explorar o 2D no Unity, que se baseia no suporte 2D do Unity adicionado na versão 4.3. Você podia fazer 2D no Unity antes da versão 4.3, mas o processo era muito doloroso sem um kit de ferramentas de terceiros. O que eu quero é somente arrastar e soltar uma imagem na minha cena e que ela apareça e funcione como eu esperava através da interface arrastar/soltar. Isso é uma das coisas que o Unity 4.3 traz para a mesa e, neste artigo, discutirei mais dos seus recursos ao desenvolver um jogo básico na plataforma 2D para aprender alguns conceitos essenciais do Unity.

2D no Unity

Para obter suporte 2D no Unity, ao criar um novo projeto você seleciona 2D da lista suspensa no diálogo do novo projeto. Quando você seleciona, os padrões do projeto são definidos para 2D (exibidos em Editar | Configurações do projeto | Editor) e qualquer imagem importada para seu projeto são trazidas como sprites em oposição à apenas texturas. (Eu abordarei isso na próxima seção.) Além disso a exibição da cena também usa o padrão do modo 2D. Isso realmente apenas fornece um botão de ajuda que fixa você em dois eixos durante o desenvolvimento da cena, mas não tem efeito no seu jogo real. Você pode clicar nele a qualquer momento para entrar e sair do modo de trabalho 2D. Um jogo em 2D no Unity é realmente ainda um ambiente 3D; seu trabalho é apenas restrito aos eixos X e Y. As Figuras 1 e 2 mostram o modo 2D selecionado e não selecionado. Eu tenho a câmera destacada para que você possa ver um contorno da área de exibição da câmera, mas observe que ele olha para o espaço como uma formato retangular.

Modo 2D selecionado—a câmera tem foco
Figura 1 Modo 2D selecionado—a câmera tem foco

Modo 2D não selecionado—a câmera tem foco
Figura 2 Modo 2D não selecionado—a câmera tem foco

A câmera destacada é configurada como uma câmera ortográfica, um ou dois modos de câmera no Unity. Esse tipo de câmera, que é geralmente usado em 2D, não dimensiona objetos de longe como seus olhos iriam ver eles, ou seja, não há profundidade da posição da câmera. O outro tipo de câmera é a perspectiva, que mostra objetos como seus olhos veriam eles, com profundidade. Há vários motivos para usar um tipo de câmera em vez do outro, mas em geral, escolha a perspectiva se precisar de profundidade visual, a menos que queira dimensionar seus objetos de forma apropriada. Você pode alterar o modo simplesmente selecionando a câmera e alterando o tipo de projeção. Eu recomendo experimentar isso e ver como que a área de exibição de sua câmera se altera quando você começa a mover os objetos para longe para dentro do eixo Z. Você pode alterar o modo de comportamento padrão a qualquer momento, o que afeta somente a importação futura de imagens para seu projeto.

Se você tiver um projeto existente no Unity ou não tem certeza se selecionou o 2D da caixa de diálogo do projeto, é possível configurar o padrão do projeto para 2D ao ir até Editar | Configurações do Projeto | Editor; caso contrário, será necessário configurar manualmente o tipo de textura em cada imagem 2D que você importar, o que é um pouco entediante se você tiver muita arte.

Tudo está relacionado ao sprite

Quando o 3D é selecionado como o modo de comportamento padrão, as imagens são reconhecidas como tipo Textura. Você pode arrastar uma textura para sua cena; uma textura deve ser aplicada a um objeto. Dessa maneira não é muito divertido criar jogos 2D. Eu quero apenas arrastar e soltar uma imagem e ter ela aparecendo na minha cena. Se o seu modo de comportamento padrão é 2D, no entanto, as coisas se tornam mais fáceis. Quando eu arrasto e solto uma imagem no Unity, ela é agora reconhecida como tipo Sprite.

 Isso permite que você simplesmente arraste e solte sua arte no Unity, e arraste e solte ela na sua cena para criar seu jogo no Unity. Se você tem arte que parece pequena, em vez de redimensioná-la em todos os lugares, é possível apenas diminuir os valores de pixels para unidades. Essa é uma operação bastante comum no Unity tanto para 2D como 3D e geralmente tem mais desempenho do que dimensionar objetos através de sua propriedade de dimensionar do Transform. 

Ao soltar objetos, você pode observar que um objeto vai parar em cima do outro. O Unity cria uma série de vértices atrás das cenas, até para imagens 2D, portanto, a ordem do desenho pode ser diferente em várias partes das imagens. É sempre melhor especificar explicitamente a ordem z das suas imagens. Você pode fazer isso através de três métodos, listados na ordem que o Unity desenha seus sprites:

  1. Configurar a propriedade “Camada de classificação” no renderizador sprite.
  2. Configurar a propriedade “Ordem na camada”, também no renderizador sprite.
  3. Configurar o valor da posição Z do Transform.

A camada de classificação tem prioridade sobre todos, seguido pela ordem na camada, que por sua vez tem prioridade sobre o valor z do transform.

As camadas de classificação desenham na ordem de definição. Quando você adiciona outras camadas (em Editar | Configurações de Projeto | Marcas e Camadas), o Unity desenha qualquer objeto que ele achar na camada padrão primeiro (a Ordem na camada assume o controle, o valor da posição Z do Transform), o Plano de fundo, as Plataformas e assim por diante. Dessa maneira, você pode corrigir facilmente as imagens de sobreposição configurando-as para a camada de plataformas e dando a uma que você quer na parte superior uma Ordem na camada do 1, assim ela será desenhada antes de qualquer coisa com Ordem na camada do 0.

Funcionalidade comum

A Figura 3 mostra um nível contendo algumas plataformas e imagens em segundo plano que foram criadas ao arrastar e soltar e configurar as camadas de classificação.

Um nível de jogo
Figura 3 Um nível de jogo

Como está agora, parece como um jogo, mas não age como um. No mínimo, precisa de um número de recursos para ser um jogo funcional. Eu discutirei vários deles nas seções a seguir.

Teclado, Mouse e Movimento de toque No Unity, o teclado, mouse, acelerômetro e toque são lidos através do sistema de entrada. Você pode ler o movimento de entrada e os cliques ou toques do mouse facilmente usando um script como o seguinte no jogador principal (Eu compilarei este script em breve.):

void Update()
{
  // Returns -1 to 1
  var horizontal = Input.GetAxis("Horizontal");
  // Returns true or false. A left-click
  // or a touch event on mobile triggers this.
  var firing = Input.GetButtonDown("Fire1");
}

Se você marcar Editar | Configurações do Projeto | Entrada, é possível ver as entradas padrão (o Unity fornece a você várias que estão lá em todos os novos projetos) ou definir novas. A Figura 4 mostra os padrões para ler o movimento horizontal. As configurações “esquerda” e “direita” representam as teclas de seta esquerda e direita, mas observe também que o “a” e “d” são usados para o movimento horizontal. Elas podem mapear para as entradas de joystick. Você pode adicionar novas ou alterar as padrões. O campo de confiabilidade controla o quão rápido o Unity irá de 0 a 1 ou -1. Quando a seta correta é pressionada, o primeiro quadro pode produzir um valor de .01 e depois dimensionar bem rápido até 1, embora você possa ajustar a velocidade para fornecer ao seu personagem movimento ou velocidade horizontal instantânea. Eu lhe mostrarei o código em seguida para aplicar estes valores ao seus objetos do jogo. Não há componente GameObject real necessário para ler estes valores; você simplesmente usa o teclado de entrada no seu código para acessar a funcionalidade para a entrada de leitura. A entrada, como regra geral, deve ser lida na função Atualizar em oposição ao FixedUpdate para evitar perder eventos de entrada.

Padrões de entrada horizontal
Figura 4 Padrões de entrada horizontal

Movimento linear As coisas precisam se mover. Se esse for um jogo de cima para baixo, geralmente a gravidade não é importante. Se for uma plataforma, a gravidade é extremamente importante. Em ambos os casos, a detecção da colisão do objeto é crítica. Aqui encontram-se as regras básicas. Um componente Rigidbody2D ou RigidBody (usado para 3D) adicionado a um objeto do jogo fornecerá automaticamente ao componente massa e fará com que ele compreenda a gravidade e receba força. De acordo com a Wikipédia, “Em física, um corpo rígido é uma idealização de um corpo sólido na qual a deformação é negligenciada. Em outras palavras, a distância entre quaisquer determinados dois pontos de um corpo rígido permanece constante no tempo, independentemente de forças externas exercidas sobre ele”. O mesmo princípio se aplica aos jogos. Adicionando um corpo rígido permite que você faça chamadas como aquelas na Figura 5.

Figura 5 Adicionando movimento e velocidade

void FixedUpdate()
{
  // -1 to 1 value for horizontal movement
  float moveHorizontal = Input.GetAxis("Horizontal");
  // A Vector gives you simply a value x,y,z, ex  1,0,0 for
  // max right input, 0,1,0 for max up.
  // Keep the current Y value, which increases 
  // for each interval because of gravity.
  var movement = new Vector3(moveHorizontal * 
    _moveSpeed, rigidbody.velocity.y, 0);
  rigidbody.velocity = movement;
  if (Input.GetButtonDown("Fire1"))
  {
    rigidbody.AddForce(0, _jumpForce, 0);
  }
}

Como uma regra geral, o movimento linear deve ocorrer através da Atualização e o movimento acelerado através do FixedUpdate. Se você for um iniciante, pode parecer confuso o que usar e quando usar, e, na verdade, o movimento linear funcionará em ambas as funções. Porém você obterá resultados visuais melhores se seguir esta regra.

Detecção de colisão Um objeto obtém sua massa do seu componente RigidBody, mas você também precisa dizer para o Unity como lidar com as colisões com este objeto. O tamanho e a forma da sua arte ou modelos não importa aqui, embora o dimensionamento afeta a física do próprio objeto. O que importa é o tamanho e a forma do componente do colisor, que é simplesmente uma região definida em volta, sobre ou dentro do objeto que você deseja que o Unity detecte outro contato de objeto. É isso que possibilita cenários como, por exemplo, a detecção quando você entra na região de um zumbi inativo ou de pedregulhos que descem um lado da montanha na aproximação.

Há vários colisores formatados. Um colisor para 2D pode ser um circulo, lado, polígono ou caixa. Os Box colliders são excelentes para objetos com formatos como os quadrados ou retângulos ou quando você simplesmente deseja detectar colisões na área quadrada. Pense em uma plataforma que você possa se posicionar—esse é um bom exemplo de um box collider. Simplesmente adicionar esse componente ao seu objeto do jogo permite que você aproveite as colisões físicas. Na Figura 6, eu adicionei um circle collider e um corpo rígido ao personagem e um box collider à plataforma. Quando eu clico em jogar no Editor, o jogador imediatamente solta na plataforma e para. Nenhum código é necessário.

Adicionando colisores
Figura 6 Adicionando colisores

Você pode mover e redimensionar a região coberta por um colisor alterando suas propriedades no componente do colisor. Por padrão, os objetos com colisores não passam um através do outro (exceto para os disparadores, que abordarei a seguir). As colisões exigem componentes do colisor em ambos os objetos do jogo e pelo menos precisam ter um componente RigidBody, a menos que seja um disparador.

Se desejo que o Unity chame meu código quando essa instância de colisão ocorre pela primeira vez, eu simplesmente adiciono o seguinte código ao objeto do jogo através de um componente de script (discutido no artigo anterior):

void OnCollisionEnter2D(Collision2D collision)
{
  // If you want to check who you collided with,
  // you should typically use tags, not names.
  if (collision.gameObject.tag == "Platform")
  {
    // Play footsteps or a landing sound.
  }
}

Disparadores Às vezes você deseja detectar uma colisão, mas não quer nenhuma física envolvida. Pense em um cenário como pegar um tesouro em um jogo. Você não quer que as moedas sejam chutadas pelo jogador quando ele se aproxima, você quer que as moedas sejam pegas e não interfiram no movimento do jogador. Nesse caso, você usa um colisor chamado de disparador, que não é nada mais do que um colisor com a caixa de seleção IsTrigger habilitada. Isso desativa a física e o Unity somente chamará o seu código quando o objeto A (que contém o colisor) vem para dentro da região do objeto B (que também tem um colisor). Nesse caso, no método do código é OnTriggerEnter2D em vez do OnCollisionEnter2D:

void OnTriggerEnter2D(Collider2D collider)
{
  // If the player hits the trigger.
  if (collider.gameObject.tag == "Player")
  {
    // More on game controller shortly.
    GameController.Score++;
    // You don’t do: Destroy(this); because 'this'
    // is a script component on a game object so you use
    // this.gameObject or just gameObject to destroy the object.
    Destroy(gameObject);
  }
}

Uma coisa para lembrar é que com disparadores, não há interação física, é basicamente apenas uma notificação. Os disparadores também não exigem um componente Rigidbody, pois não são realizados cálculos de força.

Uma coisa que geralmente engana os novos desenvolvedores é o comportamento dos corpos rígidos quando você adicionar colisores a eles. Se eu tiver um circle collider no meu objeto e eu colocar este objeto em um plano inclinado (conforme indicado pelo formato do colisor), ele começa a rolar, como mostra a Figura 7. Isso modela o que você veria no mundo físico se uma roda fosse colocada em um plano inclinado. O motivo pelo qual não uso um box collider para o meu personagem é porque uma caixa tem lados que podem ser apanhados ao mover sobre os outros lados dos colisores, resultando em um experiência menos tranquila. Um circle collider torna isso mais tranquilo. No entanto, para momentos em que uma rotação suave não é aceitável, você pode usar a configuração Fixed Angle no componente de Rigidbody.

Usando um Circle Collider para um movimento suave
Figura 7 Usando um Circle Collider para um movimento suave

Áudio Para ouvir som, você precisa de um componente de Audio Listener, que já existe em todas as câmeras por padrão. Para reproduzir um som, basta adicionar um componente de Audio Source para um objeto do jogo e configurar o clipe de áudio. O Unity oferece suporte para a maior parte dos formatos de áudio mais importantes e codificará clipes mais longos para o MP3. Se você tiver várias fontes de áudio com clipes atribuídos no Editor do Unity, lembre-se de que todos eles serão carregados no tempo de execução. Ao invés, você pode carregar o áudio através do código localizado em uma pasta de recurso especial e destrui-la quando concluir.

Quando eu importei áudio para o meu projeto, eu o guardei como um arquivo WAV, que é áudio não compactado. O Unity recodificará o seu áudio mais longo para otimizá-lo, portanto, sempre use o áudio de melhor qualidade que tiver. Isso é especialmente verdadeiro para arquivos pequenos como efeitos de som, que o Unity não codificará. Eu também adicionei um componente de Audio Source para a minha câmera principal, apesar de não conseguir adicioná-lo a nenhum objeto do jogo. Eu então atribui o clipe de áudio Adventure a esse componente do Audio Source e selecionei o Loop, para que os loops sejam executados constantemente. E em três etapas simples, eu agora tenho música em segundo plano quando o meu jogo está reproduzindo.

GUI/Heads-Up Display Um sistema GUI pode conter várias coisas em um jogo. Pode envolver o sistema de menu, a integridade e a exibição de pontuação, armas, inventário e muito mais. Geralmente, um sistema GUI é o que você vê na tela que permanece imóvel independentemente para onde a câmera esteja olhando (embora não seja necessário). A funcionalidade GUI do Unity está no momento passando por uma revisão completa e o novo sistema uGUI vai ser lançado no Unity 4.6. Pelo fato de ainda não ter sido lançado, vou apenas discutir alguma funcionalidade básica aqui, mas confira meu blog no canal 9 para detalhes sobre o novo sistema GUI em channel9.msdn.com/Blogs/AdamTuliper.

Para adicionar texto de exibição simples para a tela (por exemplo, pontuação: 0), eu cliquei em Objeto do Jogo | Criar Outro | Texto GUI. Essa opção não existe mais no Unity 4.6, então você desejará assistir o vídeo no uGUI eu mencionei. Você pode ainda adicionar o componente Texto GUI ao objeto do jogo no 4.6 clicando no botão Adicionar Componente; está apenas ausente do menu Editor. Com o sistema GUI do Unity (herdado) existente, você não pode ver seus objetos GUI na exibição da cena, somente na exibição de jogo, que torna a criação do layout um pouco estranha. Se desejar, você pode usar o código puro para configurar sua GUI e há uma classe GUILayout que permite que você rastreie automaticamente os widgets. Mas prefiro um sistema GUI onde eu possa clicar e arrastar e trabalhar facilmente, é por isso que eu acho o uGUI muito mais superior. (Antes do uGUI, o líder nesta área foi um produto de terceiros bastante sólido chamado NGUI, que foi na verdade usado como a base do código inicial para o uGUI.)

A maneira mais fácil para atualizar este texto de exibição é simplesmente procurar ou atribuir no Editor uma referência para o objeto do jogo Texto GUI, tratá-lo como um rótulo no .NET e atualizar sua propriedade de texto. Isso torna fácil atualizar a tela Texto GUI:

void UpdateScore()
{
  var score = GameObject.Find("Score").GetComponent<GUIText>();
  score.text = "Score: 0";
}

Esse é um exemplo um pouco mais curto. Para o desempenho, armazenei em cache a referência para o componente GUIText no método Start para não ter que consultá-la em todas as chamadas de método.

Monitoramento da pontuação Monitorar as pontuações é fácil. Basta ter uma classe que expõe um método público ou propriedades para a qual definir uma pontuação. É comum em jogos ter um objeto chamando um Controlador de jogo que atua como o organizador do jogo. O Controlador de Jogo pode ser responsável por acionar o salvamento, carregamento, registro de pontuação nos jogos e muito mais. Nesse exemplo, eu posso simplesmente ter uma classe que expõe uma variável da pontuação, conforme exibido na Figura 8. Eu atribuo esse componente a qualquer objeto do jogo vazio, assim ele está disponível quando a cena é carregada. Quando a pontuação é atualizada, a GUI é atualizada. A variável _scoreText é atribuída no editor do Unity. Apenas solte qualquer objeto do jogo do GUIText nesse campo exposto ou use o widget de pesquisa onde este componente de script expõe a variável Score Text no editor.

Figura 8 Criando a variável _scoreText

public class GameController : MonoBehaviour
{
  private int _score;
  // Drag a GuiText game object in the editor onto
  // this exposed field in the Editor or search for it upon startup
  // as done in Figure 12.
  [SerializeField]
  private GUIText _scoreText;
  void Start()
  {
    if (_scoreText == null)
    {
      Debug.LogError("Missing the GuiText reference. ");
    }
  }
  public int Score
  {
    get { return _score; }
    set
    {
      _score = value;
        // Update the score on the screen
      _scoreText.text = string.Format("Score: {0}", _score);
    }
  }
}

Eu posso então simplesmente atualizar (neste exemplo) o código disparador do cogumelo conforme segue para incrementar a pontuação com cada coleta:

void OnTriggerEnter2D(Collider2D collider)
{
  if (collider.gameObject.tag == "Player")
  {
    GameController.Score++;
    Destroy(gameObject);
  }
}

Animações Assim como o XAML, as animações são criadas ao carregar diversas ações nos quadro-chaves. Eu poderia facilmente dedicar o artigo todo para as animações no Unity, mas vou ser breve aqui por causa do espaço. O Unity tem dois sistemas de animação, o sistema herdado e o mais recente Mecanim. O sistema herdado usa arquivos de animação(.ani), enquanto que o Mecanim usa estados para controlar quais arquivos de animação reproduzir.

A animação em 2D usa o Mecanim por padrão. A maneira mais simples de criar uma animação é arrastar e soltar imagens na sua cena e deixar que o Unity crie as animações para você. Para começar, eu arrasto alguns sprites únicos para o Unity e o Unity cria várias coisas para mim. Primeiro, ele cria um objeto do jogo com um componente sprite renderer para desenhar os sprites. Depois ele cria um arquivo de animação. Você pode ver isso em Janela | Animador e destacar o objeto do jogo. O animador mostra o arquivo de animação atribuído, que, no meu caso contém seis quadros-chaves porque eu soltei seis imagens na minha cena. Cada quadro-chave controla um ou mais parâmetros em alguns componentes; aqui, ele altera a propriedade Sprite do componente Sprite Renderer. As animações não são nada mais do que imagens únicas mostrando de qualquer forma que faz o olho perceber o movimento.

Depois, o Unity cria um componente Animator no objeto do jogo, conforme exibido na Figura 9.

O componente Animator apontando para um controlador
Figura 9 O componente Animator apontando para um controlador

Esse componente aponta para um computador de estado simples chamado de um controlador de animação. Esse é um arquivo que o Unity cria, que apenas mostra o estado padrão; em outras palavras, está sempre no estado “ocioso”, visto que é o único estado disponível. Esse estado ocioso não faz nada mais do que apontar para o arquivo de animação. A Figura 10 mostra os dados do quadro-chave atuais na linha do tempo.

Os dados de animação ociosos
Figura 10 Os dados de animação ociosos

Talvez pareça muito para percorrer simplesmente para reproduzir uma animação. A poder de computadores de estado, no entanto, é que você pode controlá-los definindo variáveis simples. Lembre-se, um estado não faz nada mais do que apontar para um arquivo de animação (embora em 3D você possa sofisticar e fazer coisas como combinar as animações).

Eu então peguei mais imagens para fazer uma execução de animação e soltei elas no meu objeto do jogo Yeti. Como eu já tenho um componente animator no objeto do jogo, o Unity apenas cria um novo arquivo de animação e adiciona um novo estado chamado “executar”. Eu posso simplesmente clicar com o botão direito do mouse em ocioso e criar uma transição para executar. Isso cria uma seta entre os estados ocioso e executar. Eu posso então adicionar uma nova variável chamada “Execução”, que é simples de usar—você apenas clica na seta entre os estados e altera a condição para usar a variável, conforme exibido na Figura 11.

Alterando os estados de executar para o ocioso.
Figura 11 Alterando os estados de executar para o ocioso.

Quando Execução se torna verdadeiro, o estado de animação ocioso altera para o estado de execução de animação, o que simplesmente significa que o arquivo de execução de animação é reproduzido. Você pode controlar essas variáveis no código facilmente. Se você deseja começar a sua execução de animação ao disparar o estado executar quando o botão do mouse é clicado, é possível adicionar o código mostrado na Figura 12.

Figura 12 Alterando o estado com o código

private Animator _animator;
void Awake()
{
    // Cache a reference to the Animator 
    // component from this game object
    _animator = GetComponent<Animator>();
}
void Update()
{
  if (Input.GetButtonDown("Fire1"))
  {
    // This will cause the animation controller to
    // transition from idle to run states 
    _animator.SetBool("Running", true);
  }
}

Em meu exemplo, eu usei sprite únicos para criar uma animação. No entanto, é bastante comum usar uma folha de sprite—um arquivo único de imagem com mais de uma imagem nele. O Unity oferece suporte às folhas de sprite, então é uma questão de dizer para o Unity como cortar seu sprite e depois soltar estes cortes na sua cena. As únicas etapas diferentes é mudar o modo sprite de único para múltiplo nas propriedades sprite e abrir o editor do sprite, o que pode cortar automaticamente o sprite e aplicar as alterações, conforme exibido na Figura 13. Finalmente, você expande o sprite (há uma pequena seta no ícone do sprite na exibição do projeto), destaca os sprites resultantes e solta-os na sua cena como você fez antes.

Criando uma folha de sprite
Figura 13 Criando uma folha de sprite

A animação pode ser um assunto complicado até você aprender como usar o sistema. Para obter mais informações, consulte meu blog no canal 9 ou um dos muitos bons recursos no site de aprendizagem do Unity.

O fim do nível Quando o jogador chega ao fim do nível, você pode simplesmente ter um colisor que é definido para um disparador e permitir que o jogador atinja aquela zona. Quando ele atinge, você apenas carrega outro nível e recarrega o atual:

void OnTriggerEnter2D(Collider2D collider)
{
  // If the player hits the trigger.
  if (collider.gameObject.tag == "Player")
  {
    // Reload the current level.
    Application.LoadLevel(Application.loadedLevel);
    // Could instead pass in the name of a scene to load:
    // Application.LoadLevel("Level2");
  }
}

O objeto do jogo e suas respectivas propriedades são exibidas na Figura 14. Observe que a altura do colisor é alta o suficiente para que o jogador não possa pular sobre ele e também que este colisor seja definido como um disparador.

O objeto do jogo e suas propriedades
Figura 14 O objeto do jogo e suas propriedades

Jogo Em um jogo 2D simples como este, o fluxo é bastante direto. O jogador começa. A gravidade no corpo rígido faz o jogador cair. Há um colisor no jogador e na plataforma, portanto, o jogador para. O teclado, mouse e entrada por toque são lidos e movem o jogador. O jogador pula entre as plataformas ao aplicar o rigidbody.AddForce para fazer ele pular e move para esquerda ou direita ao ler o Input.GetAxis­(“Horizontal”) e ao aplicar ele para o rigidbody.velocity. O jogador colhe cogumelos, que são apenas colisores definidos como disparadores. Quando o jogador toca neles, eles incrementam a pontuação e destroem a si próprios. Quando o jogador finalmente chega até o último sinal, há um colisor/disparador que simplesmente recarrega o nível atual. Um item "a fazer" adicional aqui seria para adicionar um colisor maior debaixo da terra para detectar quando o jogador cai da plataforma e simplesmente recarrega o nível, também.

Pré-fabricados A reutilização é importante na codificação, bem como no design. Quando você atribui diversos componentes e personaliza seus objetos do jogo, você os reutiliza com frequência na mesma cena ou até em cenas múltiplas ou jogos. É possível criar outra instância do objeto do jogo na sua cena, mas também pode criar uma instância de um pré-fabricado que ainda não existe na sua cena. Considere as plataformas e seus colisores. No momento você não pode reutilizá-los nas cenas. Mas isso é possível ao criar pré-fabricados. Apenas arraste qualquer objeto do jogo da hierarquia de volta para a pasta do projeto e um novo arquivo é criado com a extensão .prefab que inclui qualquer hierarquia-filho. Você pode agora arrastar esse arquivo para suas cenas e reutilizá-lo. O objeto do jogo original fica azul para notar que ele agora está conectado a um pré-fabricado. Atualizar o arquivo .prefab atualiza todas as instâncias nas suas cenas e você pode também enviar alterações por push de um pré-fabricado da cena modificada dimensionada de volta para o arquivo .prefab, também.

Clicar no pré-fabricado exibe os objeto do jogo que ele contém, conforme exibido na Figura 15. Se você fizer qualquer alteração aqui, todas as instâncias na sua cena serão atualizadas.

Exibindo o conteúdo de um pré-fabricado
Figura 15 Exibindo o conteúdo de um pré-fabricado

Conclusão

Há algumas operações comuns realizadas através dos jogos. Nesse artigo, eu abordei os conceitos básicos de um jogo de plataforma que usa colisores, corpos rígidos, animações, registro de pontuação, texto GUI básico e leitura de entrada de usuário para aplicar força para mover o jogador. Esses blocos de construção podem ser reutilizados através de uma variedade de tipos de jogos. Fique atento para uma discussão do 3D chegando no meu próximo artigo!

Aprendizagem adicional

 


Adam Tuliper é um evangelista técnico sênior da Microsoft na ensolarada California. Ele é um desenvolvedor de jogos indie, co-administrador do Orange County Unity Meetup e autor do pluralsight.com. Ele e sua mulher estão prestes a ter seu terceiro filho, portanto, entre em contato como ele enquanto ele ainda tem tempo livre em adamt@microsoft.com ou no Twitter em twitter.com/AdamTuliper.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Matt Newman (Subscience Studios), Tautvydas Žilys (Unity)