Este é o primeiro de dois tutoriais sobre como orientar um objeto em direção a outro no Unity. Especificamente, veremos como fazer o modelo 3D de uma câmera de vigilância se orientar automaticamente em direção ao Player, acompanhando seus movimentos dentro da cena.


O áudio deste tutorial não está disponível em Português. Abaixo, você pode assistir ao vídeo com áudio em Inglês e legendas em Português, Inglês e outros idiomas. Abaixo do vídeo, você encontrará a transcrição traduzida para o Português.


Transcrição do vídeo

Olá a todos!

Este é o primeiro de dois tutoriais sobre como orientar um objeto em direção a outro no Unity. Especificamente, veremos como fazer o modelo 3D de uma câmera de vigilância se orientar automaticamente em direção ao Player, acompanhando seus movimentos dentro da cena.

Este tutorial foi criado usando Unity 2022 e está dividido em duas partes.

Na primeira parte, vamos analisar o problema e abordá-lo utilizando o método Rotate para obter uma rotação instantânea da câmera.

Na segunda parte, utilizaremos quaternions e o método Slerp para criar rotações mais suaves e graduais.

Vamos analisar o problema a ser resolvido antes de passar para a implementação.

A câmera pode girar apenas em torno do seu eixo vertical local, portanto podemos reduzir o problema ao plano 2D. Para tornar esse aspecto mais compreensível, estou enquadrando a cena a partir da visualização TOP em modo Orthogonal.

Tanto o modelo 3D da câmera de vigilância quanto o Player possuem, como todos os game objects, coordenadas de Position XYZ que identificam sua posição na cena.

Não estamos interessados na coordenada position.y, porque a câmera só pode girar em torno desse eixo LOCAL, então consideraremos apenas as coordenadas de posição x e z, como se os dois objetos estivessem no mesmo plano, com o mesmo valor para suas coordenadas y.

No nosso caso, além disso, a câmera de vigilância pode ser considerada como a origem do sistema de referência, ou seja, como a origem em um plano cartesiano, no ponto 0,0.

Não só isso, mas também podemos considerar a direção enquadrada pela câmera, que neste caso corresponde ao eixo LOCAL Y negativo, como um dos eixos cartesianos.

Podemos então identificar a direção que conecta a câmera virtual à posição do Player na cena. Isso é simplesmente um vetor, que neste caso também consideraremos apenas em duas dimensões, ou seja, GLOBAL X e Z.

Conclui-se, portanto, que a rotação que queremos aplicar à Surveillance Camera é dada pelo ângulo que separa a orientação do asset, ou seja, seu eixo local Y negativo, e o vetor ideal que conecta a Surveillance Camera ao Player. Ao encontrar esse ângulo, teremos a rotação a ser aplicada ao modelo 3D em torno do seu eixo vertical local.

Temos muita sorte: existe uma função matemática chamada arco tangente de dois argumentos, implementada pelo método Atan2 em Mathf, que calcula exatamente esse ângulo recebendo como parâmetro o vetor direção, dado pela diferença entre as coordenadas dos dois pontos.

Especificamente, Atan2 considera o ângulo entre o eixo X do plano cartesiano e o vetor direção entre a origem e o alvo.

No nosso caso, a origem é dada pelas coordenadas X e Z do modelo 3D da Surveillance Camera, portanto as coordenadas do alvo x e y serão dadas pelas diferenças de coordenadas entre a câmera de vigilância e o Player, enquanto o eixo X coincide com o eixo local Y negativo da Surveillance Camera.

A função recebe os dois parâmetros em ordem inversa. No plano cartesiano, de fato, temos atan2(y, x). No nosso caso, considerando o sistema de referência do Unity, onde o eixo x é lateral, o eixo z é frontal e o eixo y é vertical, que não consideramos aqui, escreveremos atan2(x, z).

A documentação online do Unity informa que Mathf.Atan2 recebe as coordenadas y e x, que no nosso caso serão x e z, e retorna como valor float o ângulo em radianos cujo tangente é y dividido por x.

A função Rotate no Unity requer um ângulo de rotação EM GRAUS, então teremos que levar em conta essa diferença de unidade de medida, e a conversão necessária, ao escrever o código.

Agora que analisamos o problema e sua solução, vamos passar para a primeira implementação: rotação instantânea com Rotate.

Primeiro, crio um novo script C# chamado LookAtObject para ser associado à câmera de vigilância real. Digo câmera de vigilância real porque esse asset é, na verdade, composto por três elementos: uma base para ser fixada na parede, um elemento pivot e a câmera.

Estamos interessados em fazer a câmera girar em torno do SEU eixo vertical, ou seja, em torno do seu eixo vertical LOCAL.

No universo virtual do Unity, o eixo vertical GLOBAL é o eixo y, mas cada objeto pode ter seu próprio sistema de referência LOCAL. No caso do modelo 3D da câmera de vigilância, esse é o eixo Z LOCAL, como podemos ver ao alternar para o modo de exibição LOCAL no editor do Unity.

Essa distinção introduz uma leve complexidade no nosso projeto. Precisaremos calcular o ângulo de rotação no plano global da cena, utilizando as coordenadas X e Z dos objetos, e depois realizar a rotação em torno do eixo vertical local do asset.

Primeiro, criamos uma referência ao objeto a ser seguido, criando uma variável Transform chamada objectA, que associaremos ao Player no Inspector.

[SerializeField] private Transform objectA;

Feito isso, podemos ir diretamente para Update para implementar a solução discutida anteriormente. Lembro que o eixo vertical LOCAL da câmera é o seu eixo Z.

Precisamos de apenas três linhas de código.

Na primeira, calcularemos o ângulo que separa a orientação atual da câmera daquela que ela deveria ter, para apontar para o objeto.

Na segunda, calcularemos a quantidade de rotação a ser realizada em torno do eixo Z local da câmera para alcançar a orientação desejada.

Na terceira, realizaremos a rotação efetiva com o método Rotate, ao qual precisaremos fornecer dois parâmetros: o vetor vertical local e a quantidade de rotação a ser realizada em torno desse vetor.

Vamos começar calculando o ângulo entre a orientação da Surveillance Camera e aquela que ela deveria ter, usando a função Atan2 de Mathf, que retorna um valor em radianos que converteremos para graus.

Vimos que, no plano 2D, Atan2 recebe dois parâmetros: a diferença entre as coordenadas Y e a diferença entre as coordenadas X dos dois pontos, alvo e observador, nessa ordem.

No nosso cenário, com o sistema de coordenadas global do Unity, onde X e Z estão no plano 2D enquanto o Y GLOBAL identifica o eixo vertical da cena, precisaremos escrever:

float theta = Mathf.Atan2((objectA.transform.position.x - transform.position.x), (objectA.transform.position.z - transform.position.z)) * Mathf.Rad2Deg;

Feito isso, podemos passar para a segunda instrução, o cálculo da rotação a ser realizada, em graus, que pode ser feito facilmente com:

float deltaAngle = Mathf.DeltaAngle(transform.eulerAngles.z, theta);

onde transform.eulerAngles.z representa a orientação atual da câmera de vigilância, enquanto theta representa a orientação, calculada na etapa anterior, que ela deve assumir.

A terceira e última instrução nos permite girar a Surveillance Camera:

transform.Rotate(Vector3.forward, deltaAngle);

Observe que usei Vector3.forward, que identifica o eixo Z LOCAL do objeto, como vetor em torno do qual realizar a rotação. Isso ocorre porque, no caso específico desse modelo 3D, o eixo Z LOCAL não é o que indica frente e trás, mas sim o eixo vertical local do objeto.

Salve o script, volte ao editor do Unity e pressione Play para avaliar o resultado final.

NOTA. Se você perceber que a Surveillance Camera não está apontando para o alvo, verifique se os valores iniciais de XYZ Rotation da Surveillance Camera estão definidos como 0 no Inspector e tente novamente.

Recapitulando, nesta primeira parte analisamos o problema a ser resolvido e vimos como considerar os dois objetos no mesmo plano, como calcular o vetor direção e, principalmente, como aplicá-lo ao caso específico da Surveillance Camera, levando em conta seu sistema de referência local.

Em seguida, aplicamos uma rotação instantânea ao objeto, fazendo com que ele aponte para o Player a cada frame do jogo, utilizando a função Rotate.

Na próxima parte, veremos como calcular os quaternions de rotação e usar a função Slerp para girar o objeto de forma mais lenta e suave.

Pesquisar nos Tutoriais

Digite uma frase ou várias palavras-chave separadas por vírgulas para pesquisar.

Modelos 3D, tutoriais e recursos de computação gráfica de Francesco Milanese. As licenças de uso dos modelos 3D podem ser adquiridas nas lojas externas indicadas pelos links nas respectivas páginas, conforme os termos de licença aplicáveis. Francesco Milanese — Número de IVA: 06321250877. Contato: info@francescomilanese.com


INFORMAÇÕES DE POLÍTICA DE PRIVACIDADE AVANÇADAS E USO DOS FICHEIROS DE COOKIES