Como fazer a câmera seguir o jogador em jogos 2D na Unity

Neste tutorial, nós vamos fazer a câmera seguir o jogador em jogos 2D top down. Iremos criar dois tipos de câmera. A primeira, irá simplesmente seguir o jogador e funciona muito bem jogos com pouco ação, como RPGs. A segunda câmera permitirá que o jogador mova o mouse para olhar ao seu redor e será ótima para com mais ação, como shooters.

Este tutorial é a segunda parte de uma série de três tutoriais. Na primeira parte criamos a movimentação do personagem. E na terceira e última parte adicionaremos animações ao personagem.

Apesar de não ser necessário ler a primeira parte, recomendo ao menos dar uma olhada na primeira parte pois o que faremos aqui é uma continuação direta do que fizemos na parte anterior. 

Porém independente de ter lido ou não a primeira parte, caso encontre algum problema fique a vontade para perguntar. Farei o possível para ajudar você.

Os assets que usei estão disponíveis aqui, mas eles não são necessários e você pode usar o que você quiser.

O projeto final está disponível no GitHub.

Movendo a câmera

Na primeira parte desta série de tutoriais fizemos o personagem se mover e colidir com obstáculos no cenário, a próxima etapa é fazer com que a câmera siga ele. Como dito no início do tutorial, vamos criar dois tipos de câmera.

A primeira irá simplesmente seguir o personagem. Ela funciona muito bem para jogos com menos ação ou se você não quiser que o jogador não tenha muito tempo de resposta.

A segunda é mais flexível, além da posição do jogador, também usamos a posição do mouse para calcular a distância que a câmera deve ficar do jogador. Isso permite, que conforme o mouse se mova, o jogador tenha uma visão melhor dos seus arredores. Ela é ótima para jogos com bastante ação.

Primeiro, na pasta de scripts do nosso projeto, vamos criar um novo script. 

Selecione a pasta “Scripts” e dentro dela, clique com o botão direito, no menu que se abriu, selecione “Create > C# Script”. Nomeie o arquivo como “CameraController”.

Selecione o GameObject “Main Camera”, ele foi criado automaticamente quando criamos o projeto. 

Na janela “Inspector”, confira se no dropdown “Tag”, “MainCamera” está selecionado, se não clique no dropdown e selecione essa tag. Vamos usar ela mais tarde para encontrar uma referência a essa câmera no nosso script.

Em seguida, adicione o script “CameraController” ao GameObject. Para isso na janela “Inspector” clique no botão “Add Component” e procure pelo nome do script e clique no nome dele.

Uma forma alternativa de adicionar scripts é selecionar o GameObject “Main Camera”, em seguida, clicar e arrastar o script até a janela “Inspector”.

Criando a primeira câmera

Após criar e adicionar o script “CameraController” ao GameObject “Main Camera” dê dois cliques no script para abrir ele em seu editor de texto.

Com script aberto, digite o seguinte código nele:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraContoller : MonoBehaviour
{
    [SerializeField]
    private Transform target;

    private void LateUpdate()
    {
        transform.position = new Vector3(target.position.x, target.position.y, transform.position.z);
    }
}

Agora volte ao editor, selecione a câmera e na janela “Inspector” você notar que um novo campo apareceu no script “CameraController” com o nome “Target”. Clique e arraste o GameObject que representa o personagem para esse campo.

Em seguida, clique no botão para entrar no “Play Mode” e mova o personagem.

A câmera deve seguir o personagem agora.

Vamos entender o que o código está fazendo.

Primeiro declaramos a variável target, ela irá guardar uma referência ao GameObject que queremos que a câmera siga, no nosso caso, o personagem. Também marcamos ela com o atributo SerializeField para que possamos modificar seu valor diretamente na engine.

[SerializeField]
private Transform target;

O método LateUpdate() é chamado pela Unity após o método Update(), isso garante que a câmera só se mova após o personagem ter se movido, evitando que pareça que ele está tremendo.

Em seguida criamos um novo Vector3 para representar a nova posição que a câmera deve estar. Essa posição é construída a partir das coordenadas x e y do personagem, e, da coordenada z da própria câmera, isso garante que ela irá manter a distância correta do personagem.

private void LateUpdate()
{
    transform.position = new Vector3(target.position.x, target.position.y, transform.position.z);
}

Criando a segunda câmera

Agora que a câmera segue o personagem do jogador, vamos fazer com que a câmera leve em consideração a posição do mouse na tela para calcular sua posição. Isso irá permitir que o jogador mova o mouse para que ele olhe ao redor do personagem.

Volte o seu editor de texto e vamos modificar o script CameraController. Digite o seguinte código:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraContoller : MonoBehaviour
{
    [SerializeField]
    private Transform target;
    [SerializeField]
    private Vector2 targetOffset;

    private void LateUpdate()
    {
        Vector3 mouseScreenPosition = Camera.main.ScreenToViewportPoint(Input.mousePosition);

        mouseScreenPosition.x = (mouseScreenPosition.x - 0.5f) * 2f;
        mouseScreenPosition.y = (mouseScreenPosition.y - 0.5f) * 2f;

        mouseScreenPosition.x = Mathf.Clamp(mouseScreenPosition.x, -1f, 1f);
        mouseScreenPosition.y = Mathf.Clamp(mouseScreenPosition.y, -1f, 1f);

        float offsetX = targetOffset.x * mouseScreenPosition.x;
        float offsetY = targetOffset.y * mouseScreenPosition.y;

        Vector3 cameraPosition = new Vector3(target.position.x + offsetX, target.position.y + offsetY, transform.position.z);

        transform.position = cameraPosition;
    }
}

Não se preocupe se não entender o que está acontecendo de cara, levou um tempo para eu entender como ele funciona. Mas depois que você compreender verá que esse código é bem mais simples do que parece. E que apenas usamos um pouco de matemática para mapear a posição do mouse para um valor entre -1 e 1. Vou explicar com mais detalhe abaixo.

Primeiro declaramos a variável targetOffset no início do script, e marcamos ela com o atributo SerializeField. Nós iremos modificar ela no editor com o valores que queremos que a câmera possa se deslocar da posição do jogador.

[SerializeField]
private Vector2 targetOffset;

Agora nós precisamos descobrir a posição do mouse na tela, graças a Unity isso é bem simples. Primeiro nós usamos Input.mousePosition, isso retorna a posição do mouse em pixels, isso é, a posição do mouse levando em consideração a resolução da tela.

Vector3 mouseScreenPosition = Camera.main.ScreenToViewportPoint(Input.mousePosition);

Em seguida nós passamos esse valor para o método ScreenToViewportPoint, este método converte a posição do mouse, que está em pixel, em um valor de 0 a 1. Só que para isso nós precisamos de uma referência a uma câmera, e é exatamente isso que Camera.main faz, essa variável fornecida pela Unity retorna a primeira câmera na cena que tenha a tag “MainCamera”. Lembra que garantimos que nossa câmera tivesse essa tag mais cedo. Guardamos o resultado na variável mouseScreenPosition.

Em seguida, iremos mapear valor de 0 a 1 para -1 a 1. Para isso nós iremos pegar cada elemento que compõe essa coordenada, subtrair 0.5 e multiplicar por 2. Por exemplo, se o mouse estiver na posição “0, 0”, quando subtrairmos 0.5 teremos a posição “-0.5, -0.5” e se multiplicarmos esse valor por 2 teremos a posição final de “-1, -1”. Para entender melhor o que está acontecendo, recomendo fazer essa conta algumas vezes com valores diferentes e verá que o resultado sempre estará entre -1 e 1.

mouseScreenPosition.x = (mouseScreenPosition.x - 0.5f) * 2f;
mouseScreenPosition.y = (mouseScreenPosition.y - 0.5f) * 2f;

Nas linhas seguintes, nós usamos Mathf.Clamp para grampear o valor da posição entre os valores que queremos. Precisamos fazer isso porque a posição do mouse pode mudar dependendo se o jogo está rodando em tela inteira ou janela.

mouseScreenPosition.x = Mathf.Clamp(mouseScreenPosition.x, -1f, 1f);
mouseScreenPosition.y = Mathf.Clamp(mouseScreenPosition.y, -1f, 1f);

Nas linhas seguintes nós multiplicamos a distância que queremos que a câmera fique do personagem com a posição do mouse. O resultado será qual a distância máxima que a câmera deve ficar do personagem e em qual direção ela deve estar olhando.

float offsetX = targetOffset.x * mouseScreenPosition.x;
float offsetY = targetOffset.y * mouseScreenPosition.y;

Por fim, nós criamos a nova posição da câmera somando a posição do personagem com a distância que calculamos nas linhas anteriores. E atribuímos esse valor à posição da câmera.

Vector3 cameraPosition = new Vector3(target.position.x + offsetX, target.position.y + offsetY, transform.position.z);

transform.position = cameraPosition;

Agora volte ao editor, selecione a câmera e na janela “Inspector” você notar que um novo campo apareceu no script “CameraController” com o nome “Target Offset”. Você pode colocar os valores que quiser para testar o efeito, no meu caso eu escolhi “4, 3”. Se você deixar “0, 0” a câmera irá ignorar a posição do mouse.

Clique no botão para entrar no “Play Mode” e mova o personagem. A câmera deve seguir ele agora e se mover o mouse a câmera deve se mover na mesma direção.

Conclusão

Chegamos ao final da segunda parte desta série de tutoriais. Nela, vimos como fazer a câmera seguir o jogador. Vimos também como podemos usar a posição do mouse para manipular a posição da câmera.

Porém, ainda falta mais uma coisa para podermos chamar o personagem de completo e isso é animação. E na terceira e última parte é exatamente o que iremos fazer.

Não deixe de conferir. Até a próxima!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *