Aprendendo a programar jogos em Unity: consertando a câmera que atravessa as paredes do consultório

Corrigiremos um dos comportamentos indesejados apresentados no game, relativo aos modos de visualização e controle de câmera pelo jogador.

em 03/11/2024
Seja bem-vindo(a) ao GameDev: Aprendendo a programar jogos em Unity de hoje! Após concedermos o tão desejado controle da movimentação do personagem no cenário ao jogador no encontro anterior, nos deparamos com uma sequência interessante de pequenos ajustes a serem realizados, tais como os envolvendo a posição da câmera nas regiões próximas às paredes do consultório.

Hoje iremos corrigir este comportamento indesejado, dando início a uma sequência de “polimentos” no manejo de nosso personagem principal em Consultório do Dr. Tratanildo antes de implementarmos os próximos módulos do game, como os que envolverão o “tratamento de saúde” de nossos pacientes.


Caso hoje seja a primeira vez que você teve contato com o conteúdo de nossa série, sinta-se especialmente convidado a nos acompanhar, a partir do primeiro texto, em uma jornada de descobertas, experimentações e de muita diversão, construindo diversos jogos por meio da elaboração de diferentes projetos no Unity.

Mesmo se você não tiver experiência prévia na área de desenvolvimento de jogos, poderá aprender conceitos interessantes que abrangem desde a instalação e configuração da ferramenta em nossos computadores até a construção e codificação de cenas, personagens, objetos, scripts controladores de comportamentos e de regras de jogo, dentre outros elementos importantes de um game.

Dessa forma, você poderá aprender ferramentas e conhecimentos úteis que lhe ajudarão a tirar do papel os jogos que sempre sonhou em ver desenvolvidos na vida real. Venha conosco nesta caminhada rumo a novos conhecimentos!

Múltiplas câmeras

Ao atrelarmos a posição da câmera principal do game ao GameObject do personagem principal, conseguimos fazer com que o jogador pudesse explorar o ambiente por meio da movimentação de doutor Tratanildo pelo cenário. Porém, como já dito anteriormente, uma das questões levantadas tem relação com o posicionamento dinâmico do objeto que carrega consigo o componente Camera (em nosso caso, CameraDoutor) nos momentos em que realizamos deslocamentos e rotações do personagem próximo às paredes do consultório.

Existem diferentes formas de se corrigir o “mergulho” que a câmera dá em direção à parede ao rotacionarmos o personagem principal nas extremidades do cenário. Em geral, envolvem o reposicionamento do GameObject da câmera para que não perpasse os limites do consultório, o impedimento da rotação da câmera nessas situações relatadas ou a troca do ponto de vista da visualização de câmera para a primeira pessoa de forma temporária. Nossa abordagem será voltada a esta última opção, por ser uma das mais simples a serem implementadas.

Vamos iniciar as modificações no projeto abrindo-o por meio do Unity Hub. Clique duas vezes sobre o item referente ao projeto Consultório do Dr. Tratanildo; na interface inicial do Unity, na aba Project, abra a pasta Assets, Scenes e, por fim, clique duas vezes no ícone da cena ConsultorioScene. Certifique-se de estar com a aba Scene em evidência na tela, conforme exemplificado pela imagem a seguir:

Iremos duplicar o GameObject da câmera implementada em nosso encontro anterior, visando ter duas opções de visualização: em primeira e terceira pessoas. Na aba Hierarchy, clique com o botão direito sobre o objeto CameraDoutor, que se encontra subordinado a Doutor_rindo. No menu suspenso que será apresentado, selecione a opção Duplicate:

Conceda o nome “CameraDoutor_interna”, sem as aspas, para o novo objeto criado. Na aba Inspector, conceda os seguintes valores aos atributos do componente Transform de CameraDoutor_interna:
  • Position X = 0, Y = 0.06, Z = 0.008;
  • Rotation X = 5, Y = -8, Z = 0.
Ao final, deixe vazia a caixa de seleção (destacado em azul na imagem a seguir) para o objeto CameraDoutor_interna. Por fim, via aba Inspector, aproveite para renomear o objeto CameraDoutor para “CameraDoutor_externa”(destacado em verde a seguir):

Visando controlarmos o comportamento de ativação e desativação para cada uma das câmeras configuradas ao se identificar que há a necessidade de se realizar tal ação, teremos de desenvolver um novo script que, posteriormente, será atrelado ao GameObject do personagem principal. Para tal, via aba Project, crie um novo script de nome “ControllerCamerasDoutor” dentro da pasta Assets/Scripts:

Clique duas vezes sobre ControllerCamerasDoutor para iniciarmos sua edição no Visual Studio.

Limites do cenário

Ao iniciarmos a edição do novo script, primeiro teremos de declarar algumas variáveis que irão se comunicar com os elementos de nosso cenário. 

Logo após a primeira abertura da chave ‘{‘ , insira o seguinte trecho de código:

    public Camera cameraInterna, cameraExterna;
    public Vector3 cenarioMin, cenarioMax;

Essas variáveis serão responsáveis para que possamos indicar ao script quais são os objetos que contém componentes Camera a serem controlados pelo comportamento que iremos configurar em código (representados por cameraInterna e cameraExterna) e, também, quais são as coordenadas dos limites do cenário a serem respeitados em relação ao posicionamento das câmeras no consultório (representados por cenarioMin e cenarioMax).

Logo após, se desejar, pode deletar a função void Start() (e suas chaves) do código, pois neste script em específico não a utilizaremos.

Dentro das chaves de void Update(), insira o seguinte trecho de código:

    bool foraDosLimites =
        (cameraExterna.transform.position.x < cenarioMin.x) ||
        (cameraExterna.transform.position.z < cenarioMin.z) ||
        (cameraExterna.transform.position.x > cenarioMax.x) ||
        (cameraExterna.transform.position.z > cenarioMax.z);

Para entendermos o que este código irá realizar, primeiro precisamos contextualizar o que representarão as variáveis cenarioMin e cenarioMax em relação às coordenadas de nosso cenário.

Visualizando-se a partir de cima, temos um ambiente praticamente retangular representando nosso consultório. Cada extremidade do cenário apresenta um conjunto de coordenadas X e Z com valores distintos:

Se considerarmos que, hoje, nossa câmera acaba apresentando imagens de fora do consultório quando o personagem está próximo às paredes, pela câmera poder estar posicionada temporariamente fora dos limites do cenário, podemos pensar em uma regra para que, caso detectemos que a posição do GameObject da câmera externa esteja de fato em ambiente externo ao consultório, a câmera interna seja ativada:

Para tal, este trecho de código realiza a seguinte sequência de ações:
  • Primeiro, iremos declarar uma variável booleana temporária, chamadas foraDosLimites. Pelo seu tipo, ela pode armazenar apenas dois valores em específico: true para ‘condição verdadeira’ ou false para ‘condição falsa’.
  • Em seguida, o valor que ela armazenará dependerá da seguinte sequência de comparações:
    • Se um dos valores da posição global de cameraExterna (eixos X ou Z) for menor do que os menores valores correspondentes para o cenário (cenarioMin.x ou z) ou maior do que os maiores valores correspondentes para o cenário (cenarioMax.x ou z), teremos o valor true concedido à variável foraDosLimites.
    • Caso contrário (ou seja, o GameObject da câmera encontra-se dentro do ambiente do consultório) o valor a ser concedido para a variável foraDosLimites será false.
Logo após o código recém-inserido, introduza as duas linhas de código a seguir:

        cameraInterna.gameObject.SetActive(foraDosLimites);
        cameraExterna.gameObject.SetActive(!foraDosLimites);

As novas linhas inseridas irão aproveitar o resultado das comparações realizadas que foi armazenado em foraDosLimites para ativar o GameObject da câmera interna (em primeira pessoa) apenas se observar que a câmera externa está fora dos limites do cenário, realizando o inverso para o GameObject da câmera externa.

Salve o script, minimize o Visual Studio e volte ao editor do Unity para que possamos configurar este comportamento de fato no personagem principal de nossa aventura.

Na aba Hierarchy, selecione o objeto Doutor_rindo, subordinado a Personagens. Na aba Inspector, clique sobre o botão Add Component e adicione um componente de tipo Controller Cameras Doutor. Configure os valores de seus atributos conforme listado a seguir:
  • Camera Interna: Indique o GameObject de nome CameraDoutor_Interna;
  • Camera Externa: Indique o GameObject de nome CameraDoutor_Externa;
  • Cenario Min: X = -12.5, Y = 0, Z = -22;
  • Cenario Max: X = 27.5, Y = 0, Z = 11.5.
Embora nosso cenário concreto seja um pouquinho “torto”, esses valores mínimo e máximo para nosso ambiente nos servirão bem.

Agora, para finalizarmos as adequações de hoje, vamos realizar um pequeno ajuste para agilizar um pouco o andar de nosso personagem principal pelo cenário. Na aba Project, com a pasta Scripts em evidência, clique duas vezes sobre o ícone do script ControllerMov_Tank para abrirmos o arquivo para edição no Visual Studio.

Dentro dos colchetes da função void Update(), vamos realizar uma breve alteração em uma das linhas de código.
  • De:
    velocidadeCaminhada = Mathf.Min(velocidadeCaminhada + Time.deltaTime, 1.0f);
  • Para:
    velocidadeCaminhada = Mathf.Min(velocidadeCaminhada + (Time.deltaTime * 2), 2.0f);
Essa alteração servirá para, ao menos temporariamente, acelerarmos um pouco o passo do doutor Tratanildo pelo cenário ao movimentarmos seu objeto.

Salve o script e feche o Visual Studio. Retorne ao Unity para testarmos os comportamentos do game após as alterações que realizamos, indo à aba Game e pressionando o ícone do botão Play:

Note que, agora, ao nos movermos em direção às paredes, quando realizamos a rotação de nosso personagem não é mais exibido o conteúdo externo da cena, mas sim a visão em primeira pessoa do médico, permitindo continuarmos imersos no ambiente que estamos preparando para o game.

Ao término dos testes, interrompa a simulação, clicando novamente sobre o ícone do botão Play e retornando à aba Scene. Não se esqueça de salvar a cena (menu File, opção Save) e o projeto (menu File, opção Save Project) antes de fechar o editor.

Próximos passos

Iniciamos a implementação de necessárias correções em nosso game, visando tornar sua experiência ao jogador agradável e com o menor número possível de bugs. Hoje, um dos problemas já foi solucionado, mas ainda temos desafios a enfrentar.

Em nossos próximos encontros, prosseguiremos corrigindo alguns aspectos importantes do jogo e daremos sequência à construção dos ambientes, regras e elementos de nossa aventura.

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.