Menu

Sempre quis ser detetive? 9 jogos que farão voce se sentir um

A carreira levanta muitas curiosidades que podem ser decifradas com experiências divertidas e educativas

Leia Mais…

12 – Tutorial Intermediário – Cenário 1

E aê galerinha indie, tudo joia? Hoje vamos fazer o nosso primeiro tutorial de cenário e resolvi fazer o cenário pequeno… Isso significa que o post será pequeno? Não, pelo contrário, será o segundo maior post. Neste post vou informar a melhor forma de criar cenários, revisar o lance do material e tiling e mostrar como criar uma plataforma One Way em relação aos cenários. Porém teremos que criar também nesse tutorial, dois outros scripts importantes. Um que irá informar o local que o personagem será criado e quando a fase termina (Que no nosso caso será quando o Boss no final da fase for derrotado) e outro que irá cuidar do movimento da câmera, ou seja, esse tutorial será maiorzinho de fazer, ai ai u.u’.

Então vamos iniciar mais um post indicando qual o sprites que eu vou utilizar na construção do cenário. Para construir cenários, vocês podem procurar por Tilesets, esse é o nome dado aos sprites de construir cenários.

Os tilesets que usaremos são de onde? Chutem! Sim, são do site Game Art 2d:

Link Platform Game 
Link direto para o Download

Nossa primeira fase será uma floresta como já havia dito antes. Então após baixar, você podem importar os seguintes assets com os nomes:
floresta_background

floresta_plataforma1

floresta_plataforma2

floresta_plataforma3

floresta_plataforma_one_way1

floresta_plataforma_one_way2

floresta_plataforma_one_way3

floresta_moita

floresta_placa

O ideal mesmo aqui seria que vocês criassem todo o cenário através de uma ferramenta de edição de Imagem como o Photoshop, onde dividiriam o chão, as plataformas nuvens, backgrounds matos e tudo mais em layers separados para ficar fácil a exportação depois, porém como eu acho que muitos de vocês podem não ter experiência, então vamos fazer tudo pelo modo Hardcore no Unity mesmo.

Então exportem tudo para uma nova pasta: Resources/sprites/tiles/fase1:

Podemos deixar o background, floresta_plataforma2 e floresta_plataforma3 como Textura mesmo para que possamos transforma-los em materiais, porém com o Alpha Is Transparent para não perder a transparência da imagem. E se a opção Alpha from Grayscale tiver marcada, tire, pois sua imagem ficará toda transparente. Os demais ficam como sprites mesmo.

O próximo passo será criar uma nova Scene a qual chamaremos de Fase1:

Aqui a primeira coisa que faremos é adicionar o chão. Como viram nosso chão tem basicamente 3 partes: Começo, meio e fim. Então vamos criar um objeto vazio que daremos o nome de Chao e dentro dele criar três outros objetos Inicio, Meio, Fim:

Caso fosse feito já em um editor de imagem era só criar um Único Chao que poderia ser até mesmo um sprite, simplicando o processo e diminuindo o consumo de memória no jogo, mas vamos que vamos!

Após ter criado, aqui é bem simples. No Inicio e Fim, vamos adicionar o componente Sprite Renderer (Add Component >> Rendering >> Sprite Renderer ou apenas faz a busca pelo nome no Add Component) e selecionar os sprites floresta_plataforma1 (Para o objeto Inicio) e o floresta_plataforma2 (Para o objeto fim). Depois afaste os objetos:

Ao mover o objeto Horizontalmente, mexa direto no objeto Inicio e Fim para definir o tamanho da plataforma. Porém ao mexer verticalmente, mexa o objeto Chao, para mover todos os 3 objetos filhos igualmente:

O objeto Fim pode ficar fora do alcance da câmera sem problema. Digamos que ela vai ser o final da nossa fase. Já a altura eu recomendo muito que a parte de baixo da plataforma não fique sendo exibido na câmera, senão quiser ter que fazer mais sprites na parte de baixo:

E não se preocupe, que ao contrário do Canvas que tem os pivots, independente do tamanho da resolução da pessoa, a parte de baixo não é exibida, se mantem como você planejou a câmera. O que pode mudar são os espaços laterais dependendo da resolução, mas verticalmente, se mantem.

Próximo passo agora é criar um material chamada PlataformaFloresta, dentro da pasta Resources/materials (Botão direito na pasta >> Create >> Material):

Já inclusive podem marcar o Shader como Unlit/ exture. E a textura será a floresta_plataforma2:

Pronto, agora é só ir no objeto Meio na aba Hierarchy e adicionar o componente Mesh Filter e Mesh Renderer (Add Component >> Mesh >> Mesh Renderer e Mesh Filter) . Em Mesh Filter vamos adicionar o formato Quad:

E em Mesh Renderer vamos adicionar o Material PlataformaFloresta em Element0:

Agora é só esticar a imagem horizontalmente e deixar ela alinhada com os objetos Inicio e Fim:

Uma vez que tiver feito, mude o Tiling X quantas vezes achar necessário para sua imagem não ficar esticada:

Caso ainda sim sua imagem fique esticada, verifique se na sua textura na aba Project (floresta_plataforma2) e Inspector, se o seu Wrap Mode está como Repeat ao invés de Clamp.

Agora no Objeto Chao (O pai dos 3), vamos adicionar o Box Collider 2D e a Layer Piso (Para que nosso personagem pule, se lembra?). Caso no meu projeto que vocês baixem, não esteja com a Layer Piso, é só adicionar, é um “bug” do unity, como já expliquei antes.

Lembrando que sua Box Collider 2D deve cobrir todos os 3 filhos, para que seu personagem não caia do nada.
Caso queira testar, é só arrastar o prefab de algum dos personagens para a aba Hierarchy:

Se o seu personagem ficou muito grande como o meu, basta ir na sua Main Camera e mudar o alcance da câmera.
Caso a projeção da sua câmera seja Orthographic, você muda o Size:

Caso ela Perspective você altera o campo de visão (Field of View):

“Carlos, qual é a diferença das duas?”

Bom, a Camera Orthographic é mais comum trabalhada com conteúdos 2D, onde ela considera todos como se tivessem tudo no mesmo plano. Ou seja, mesmo que um objeto esteja mais perto ou mais longe da câmera, ele vai continuar do mesmo tamanho. Já a Camera por Perspective, ela considera o tamanho de quem está mais próximo ou mais longe da câmera. Bora para um exemplo para ficar mais claro.

Vou deixar meu personagem mais próximo da câmera, ok?

Essa é a visão do nosso jogo de cima na aba Scene. Meu personagem não está mais com o Z igual ao da plataforma, está praticamente com a cara na câmera.

Agora vamos ver isso na aba Game com a Câmera Orthographic:

Continua exatamente igual. Mas se mudarmos a câmera para Perspective:


E lá está o nosso personagem com a cara na câmera de acordo com a sua distância. Se você quiser fazer uns efeitos Parallax sem script, só posicionando os objetos mais a frente ou mais atrás, use o Perspective. Do contrário use o Orthographic que é o padrão para jogos 2D ^^

Depois de escolher a sua câmera, ajuste novamente a posição do Objecto chão para que fique algo legal.

Com isso pronto, o próximo passo agora é repetir praticamente todo o processo para a Plataforma One Way. Então vou enumerar aqui:

1 – Crie um objeto chamado PlataformaVoadora com três objetos filhos (Inicio, Meio, Fim);
2 – No objeto Inicio adicione um Sprite Renderer com o Sprite floresta_plataforma_one_way1 e no objeto Fim adicione um Sprite Renderer com o Sprite floresta_plataforma_one_way3;
3 – Distancie horizontalmente os objetos Inicio e Fim;
4 – Crie um Material na pasta Resources/materials chamado PlataformaOneWayFloresta;
5 – No PlataformaOneWayFloresta escolha o Shader Unlit/Transparent e adicione a Textura ;
6 – No objeto Meio da PlataformaVoadora, adicione o Mesh Renderer e o Mesh Filter. O Mesh Filter será o Quad e o Mesh Renderer será o material PlataformaOneWayFloresta;
7 – Ajuste a distância das 3 imagens e o Tiling do PlataformaOneWayFloresta;
8 – Aplique o Box Collider 2D e o Layer Piso no objeto PlataformaVoadora.

Caso a sua Textura floresta_plataforma_one_way2 fique com um traço indesejado embaixo:

Troque o Filter Mode de Bilinear para Point (no filter):

Caso isso ainda não funcione tente trocar o Offset do material da posição Y para 0.01 (Fica ao lado da opção Tiling).
Prontinho.

Agora vamos para o que há de novo não é mesmo, que é o Platform One Way!

O importante é primeiro por essa plataforma em um local mais alto:

Depois iremos adicionar um componente chamado Platforme Effector 2D na plataforma com o Collider (Add Component >> Physics 2D >> Platform Effector 2D):

Logo de cara não vai acontecer nada. O motivo é bem simples. Caso repare na imagem acima, no nosso box Collider 2D, tem algo chamado Used By Effector que está desmarcado. Você precisa marca-lo se quiser usar algum tipo de Effector no Collider.

Depois de marcar você vai ver que já vai surgir um arco no seu Collider:

Esse arco ai já pertence ao Platform Effector 2D. Bora entender ele então:

O Use Collider Mask serve para informar caso você queira que esse Effector só funcione com um grupo de Layers. Caso ele vá funcionar com todo mundo, você pode deixar desmarcado. Caso você crie um Layer para o personagem e quer que esse effector só funcione com o personagem e em Collider Mask selecione apenas o layer do personagem.

Use One Way servem para fazer a grande mágica, permitir que seu personagem passe por de baixo do collider sem colidir e depois fique lá em pé. Você já pode testar isso:

Legal, né? No meu caso eu ainda aumentei o pulo do personagem no prefab na aba Project, para ele dar saltos mais altos.

Voltando… Use One Way Group, serve para que o sistema do Collider funcione com vários Colliders. Confesso que nunca vi isso em prática funcionando direito.

Surface Arc determina o local em que o Collider funciona normal, ou seja, se o objeto bater não irá conseguir passar pela plataforma. O padrão é 180, o que significa que se você bater na lateral da plataforma, você não vai conseguir passar. Caso você mude para 360, então nem por baixo você vai conseguir passar, porque o collider vai funcionar normal também na parte de baixo:

Mas se você por digamos que 90:

Você vai conseguir passar mesmo tocando pela lateral do collider sem ficar preso.

As opções Use Side Friction e Use Side Bounce servem para aplicar Fricção (Resistência) e a função de “quicar” dos lados da plataformas.

“Como eu posso fazer isso?”

Bom, nós não vamos usar isso nesse tutorial, mas vou mostrar como é possível. Primeiro você criaria na aba Project um Physics2D Material (Botão direito na aba Project >> Create >> Physics2D Material) lá você pode controlar o Friction (Ou o atrito que faz as coisas que foram empurradas andarem com mais facilidade ou mais dificuldade. No caso do nosso player, não vamos ver tanta diferença afinal não o empurramos e sim mudamos a sua posição, mas no caso de aplicar força/addForce ou cair na parte encostando algo, tem efeito mais lento dependendo do atrito) ou faz seu personagem quicar que nem uma bolinha alterando o Bounciness:

Caso você aplique esse Physics2D Material ao collider da PlataformaVoadora:

Seu personagem já deve ficar quicando toda vez que toca o collider, já que aumentamos o bounciness. Pode dá play e testar e ver seu personagem pulando como se estivesse em uma cama elástica. Isso é bom para objetos que você quer que façam seu personagem pular ou caso seu personagem seja uma bola, você pode adicionar isso no collider do seu personagem!

Mas pode apagar esse Physics2D Material que não iremos utilizar.

Voltando ao Platform Effector 2D, as opções Use Side Friction e Use Side Bounce, servem para aplicar esses dois efeitos que vimos na lateral do collider. O Side Arc, define o campo que essas duas opções terão efeitos. Mas como falei, basicamente só iremos utilizar o Use One Way e o Surface Arc em 180°, beleza?

Com isso terminamos mais um item, que o Platform One Way. Próximo passo agora é repetir mais uma vez o processo que fizemos, só que agora para o Background. Então:

1 – Crie um Material chamado BackgroundFloresta na pasta Resources/materials;
2 – Troque o Shader desse material para Unlit/Texture e escolham a textura floresta_background;
3 – Criem um objeto chamado Background na aba Hierarchy e adicionem o Mesh Filter (Quad) e Mesh Renderer (Com o material BackgroundFloresta)
4 – Aumente esse objeto para que ele cubra todo o cenário atrás e alterem o Tiling caso necessário:

E para finalizar de vez a construção do cenário, você pode baixar um áudio de floresta lá no freesound.org:

https://freesound.org/search/?q=forest

O que eu usei no projeto foi esse:

https://freesound.org/people/Slanesh/sounds/31766/

Após baixar o que você gostou, adicione a pasta Resources/sounds/BGS (Lembra-se para que serve essa pasta? Sons de fundo! )

Por fim adicione o áudio a sua Main Camera com a opção Loop marcada:

Pra finalizar de vez esse cenário, basta a gente criar dois objetos chamado LimiteEsquerdo, LimiteDireito. Neles iremos posiciona-los nas extremidades da fase e adicionaremos o Box Collider 2D, para que nossos personagens fujam da scene:

Isso já vai impedir que nosso personagem saia da scene.

Complico mais um pouquinho, ou já está bom?

É sempre bom complicar mais um pouco né? Então bora lá, vou pedir para que vocês criem outras duas layers:

Uma para os objetos limites da fase e outra para o personagem principal:

Depois definimos nos Objetos LimiteEsquerdo e LimiteDireito a Layer Limite

Já no prefab do Personagem1 e Personagem2, adicionamos a Layer Personagem:

Pronto, agora vá no menu Edit >> Project Settings >> Physics 2D e na parte inferior das configurações onde tem Layer Collision Matrix, desmarque todas as interações da Layer Limites, deixando apenas a interação entre Personagem e Limites:

Com isso o Collider não vai funcionar com mais ninguém que não tenha a Layer Personagem. Legal, né? Com isso se você tiver um pássaro voando pelo cenário ou uma plataforma que se mexe, ela não vai bater nos Colliders dos objetos que tiverem a Layer Limites. Caso queira criar layers para os inimigos e tirar a interação deles com outras coisas que não sejam o Piso e o Personagem é algo possível (lembrando que no caso tem que fazer outra layers para os ataques do personagem ou marcar os ataques do personagem com a layer Personagem). Em seus jogos é muito recomendado que vocês usem essas funções para aumentar a velocidade e processamento do seu jogo, porém no tutorial eu não vou fazer por um motivo que vocês já sabem. Ao copiar o projeto do Unity para outro pc, ele perde as tags e layers selecionadas, então vou evitar o máximo utilizar layers e tags sem ser via script.

Prontinho, mas estão sentindo falta de nada não nessa fase? A gente não adicione o Pause e nem o HUD. Então crie um objeto Canvas e adicione o prefab dos dois:

E com isso nós já terminamos a construção da nossa fase, onde tivemos uma revisão dos conteúdos passados e aprendemos sobre o Platform One Way e a interação dos colliders entre diferentes layers. Porém o post não termina por aqui, ainda temos coisas importantes a fazer:

1 – Um Script que controle a fase, criando o prefab do personagem correto fora outras coisas como verificar se a fase chegou ao fim ou não (Ela vai ser dada como completa, ao derrotar o Boss que terá em todas as fases);
2 – Um Script para a câmera seguir o personagem (Ou um objeto qualquer) e não fugir dos limites do cenário;
3 – Um Script para iniciar um evento de Boss (A câmera trava em uma posição e ativar os limitadores do cenário da batalha, para que o personagem não fuja do boss).

Ou seja, se tudo foi flores até agora sem mexer em nada de código, vamos puxar um pouco do raciocínio lógico de vocês para criar esses 3 scripts!

Embora sejam três Scripts, podem ficar tranquilo que os 3 são relativamente pequenos. Então bora para o primeiro script.

Peço que criem um script (C#) chamado GCFase dentro de scrtips/controllers. Neste script por hora só iremos ter duas variáveis, sendo uma variável publica posicaoInicial do tipo Vector3 e outra do tipo inteiro que guarda qual é o nível fase (floresta =1, lago =2, caverna=3 e montanha = 4). Também vamos criar um código no método Awake e um método publico chamado finalizaFase, mas como diria o jack, vamos por parte.

Primeiro criem a variável publica:

Script: GCFase.cs

    public Vector3 posicaoInicial;
    public int nivel;

Em seguida vamos pegar o nome do prefab do personagem que o jogador selecionou e que está registrado no GameStatus, lembram? Depois daqui, é só revisão de como instanciar um objeto no cenário igual como fizemos os ataques:

Script: GCFase.cs

    void Awake() {
        //Cria o personagem na fase
        var nomePrefab = FindObjectOfType().getGameStatus().prefabPersonagem; //Busca o nome do prefab
        var prefabPlayer = Resources.Load("prefabs/jogador/" + nomePrefab);           //Busca o prefab
        var objPersonagem = Instantiate(prefabPlayer) as GameObject;                  //Cria o personagem
        objPersonagem.transform.position = posicaoInicial;
    }

Sem complicação, não é mesmo? Só pegamos o nome do prefab que temos registrado. Buscamos na pasta Resources/prefabs/jogador e criamos esse objeto. Depois definimos a sua posição no cenário. Se quiséssemos, poderíamos até deixar esse código com menos linha trocando as duas ultimas linhas por:

Instantiate(prefabPlayer, posicaoInicial, Quaternion.identity);

Onde o primeiro parâmetro é o prefab, o segundo parâmetro é a posição e o terceiro parâmetro é a rotação. O Quaternion.identify cuida de trazer o prefab sem rotação alguma, ou seja, alinhado com o cenário.

Mais simples, impossível. Agora vamos criar só mais um método público nesse script, que será chamado quando o jogador completar a fase, onde iremos liberar a próxima fase caso ainda não tenha liberada, recuperarmos a vida do nosso personagem, para que nas próximas fases ele comece com tudo cheio, atualizar a informação do jogador no GameStatus. Por fim chamar a tela de seleção de fases:

Script: GCFase.cs

    public void finalizarFase() {
        var gameStatus = FindObjectOfType().getGameStatus();                                    //Busca o GameStatus
        var status = GameObject.FindGameObjectWithTag("Player").GetComponent().getStatus();//Busca o Status do personagem ativo
        if (nivel == gameStatus.faseLiberada)                                                           //Verifica se esse nível é ultimo liberado
            gameStatus.faseLiberada++;                                                                  //Libera o próximo nivel

        status.recuperaHP(999);                     //Recupera todo HP
        status.recuperaMagia(999);                  //Recupera toda MP
        gameStatus.status = status;                 //Informa para o gameStatus o novo status do jogador.

        SceneManager.LoadScene("MenuFases");                   //Chama a scene de selação de fases
    }

Explicando, primeiro a gente buscou o GameStatus do script GCJogo. Ao alterar ele aqui, já irá alterar automaticamente lá no GCJogo, já que é passado como referencia, ok?

Sem seguida a gente buscou o Status do personagem ativo na fase.

Sem seguida verificamos o nível atual é o ultimo nível liberado. Caso sim, a gente libera o próximo nível.

Recuperamos o HP e MP do nosso personagem e passamos esse status atualizado para o gameStatus. Por fim chamamos a seleção de fases! Se lembrem que para usar o SceneManager, precisamos chamar o “using UnityEngine.SceneManagement;”.

Tudo tranquilo, então é só salvar e voltar o Unity, onde você vai criar um novo objeto com o nome GC e adicionar esse script a ele, informando uma posição que você achar legal para seu personagem começar e informar o nível da fase (1):

A posição do personagem você pode identificar usando o prefab, todavia você tem que remover o prefab da aba Hierarchy depois, pois o script GCFase já irá adicionar um. Do contrário ficará duplicado.

Pronto nosso script GCFase está finalizado por hora.

Vamos para o script da câmera. Nele iremos utilizar o GCCamera que já criamos anteriormente para controlar o som, lembra? Então já pode abrir esse script e adicionar uma nova variável, que irá receber o Transform de um objeto no cenário e outra variável do tipo float que irá definir a velocidade com a qual a câmera se mexer:

Script: GCCamera.cs

    public Transform alvo;      //Quem a camera segue
    public float velocidade;    //Com qual velocidade a camera segue

Depois disso no método Update vamos verificar se existe algum alvo. Caso sim, iremos pegar o destino que a câmera deve ir. O destino será a posição de X e Y do alvo, porém mantendo a mesma distância que a câmera foi definida (Ou seja, o Z continua sendo o camera). Depois usaremos o método Vector3.Lerp para fazer a câmera sair da sua posição original para o destino, numa velocidade que definimos:

Script: GCCamera.cs

    void Update() {
        if (alvo != null) {
            var destino = new Vector3(alvo.position.x, alvo.position.y, transform.position.z);
            transform.position = Vector3.Lerp(transform.position, destino, velocidade * Time.deltaTime);
        }
    }

“Epa, epa, epa, epa!!! No script da fase, para definir que um objeto saísse da sua posição para um destino, você usou o Vector3.MoveTowards e agora está usando o Vector3.Lerp? Qual é a diferença de cada um? Quando eu devo usar cada um?! Por que existem dois se eles fazem a mesma coisa que é sair de uma posição para ir a um destino??!! Explica ai por favor, Carlos!!!”

Calma, calma, calma. Pelo menos eu vi que você entendeu o transform.Translate. O Translate serve para sair de uma posição a outra, sem a gente saber o destino. Ou seja, eu sei que ele quer ir para a esquerda, agora o destino não sei, então uso o transform.Translante(Vector3.right * Time.deltaTime)! Agora se você sabe o destino, então você usa o Vector3.Lerp ou Vector3.MoveTowards.

Agora explicar os dois você me complica um pouco, mas vou tentar explicar de forma clara.

O Vector3.MoveTowards define:
(Posição Inicial, Posição Final, Distância real caminhada da Posição Inicial para a Posição Final)

Já o Vector3.Lerp define:
(Posição Inicial, Posição Final, Distância caminhada em porcentagem da Posição Inicial para a Final)

Não entendeu né? Vamos transformar isso em algo prático. Ao invés de um Vector3, vamos pensar em um valor linear onde temos um objeto que inicia na posição 0 e que ir pra posição 2. No caso do MoveTowards ele vai sempre andar o mesmo valor fixo:

Vector3.MoveTowards(transform.position, destino, 0.5)
Frame 1 (Executa o Update)

Transform.position: 0
destino: 2
Distância: 2
Percorre: 0.5
Posição final do objeto percorrido: 0.5

Frame 2 (Executa o Update)

Transform.position: 0.5
destino: 2
Distância: 1.5
Percorre: 0.5
Posição final do objeto percorrido: 1

Frame 3 (Executa o Update)

Transform.position: 1
destino: 2
Distância: 1
Percorre: 0.5
Posição final do objeto percorrido: 1.5

Frame 4 (Executa o Update)

Transform.position: 1.5
destino: 2
Distância: 0.5
Percorre: 0.5
Posição final do objeto percorrido: 2

Ou seja, o MoveTowards percorre uma distância real e “fixa”, entendeu? Agora vamos ver o Lerp que percorrer uma porcentagem sendo 0 (0% do caminho percorrido ou seja fica na mesma posição de origem) e 1 (100% anda o caminho todo de uma vez, ou seja fica já no destino):

Vector3.Lerp(transform.position, destino, 0.5)
Frame 1 (Executa o Update)

Transform.position: 0
destino: 2
Distância: 2
Percorre: 1 (0.5 = 50% do caminho | 50% da distância = 1)
Posição final do objeto percorrido: 1

Frame 2 (Executa o Update)

Transform.position: 1
destino: 2
Distância: 1
Percorre: 0.5 (0.5 = 50% do caminho | 50% da distância = 0.5)
Posição final do objeto percorrido: 1.5

Frame 3 (Executa o Update)

Transform.position: 1.5
destino: 2
Distância: 0.5
Percorre: 0.25 (0.5 = 50% do caminho | 50% da distância = 0.25)
Posição final do objeto percorrido: 1.75


E vai assim infinitamente até chegar perto do valor. Com isso podemos observar que o Lerp ele é mais “rápido” (percorre uma distância maior por frame) quando a distância é maior e mais “lento” (percorre uma distância menor por frame) quando a distância é menor. Com isso ele acelera no inicio e quando chega perto do destino ele vai mais lento, gerando um efeito legal de suavização.

Então podemos entender que MoveToward mantem a mesma velocidade independente da distância. Já o Lerp ele é mais rápido quando a distância é maior e mais suave quando está chegando ao destino. Basicamente é essa a diferença. Deu para entender melhor agora?

Bom, voltando ao nosso script vamos usar o Lerp, para fazer um movimento legal na câmera ao seguir o personagem. Agora de volta ao nosso script GCFase, lá no Awake, vamos definir o alvo sendo o personagem adicionando duas linhas ao final do método:

Script: GCFase.cs

    void Awake() {
        //Cria o personagem na fase
        var nomePrefab = FindObjectOfType().getGameStatus().prefabPersonagem; //Busca o nome do prefab
        var prefabPlayer = Resources.Load("prefabs/jogador/" + nomePrefab);           //Busca o prefab
        var objPersonagem = Instantiate(prefabPlayer) as GameObject;                  //Cria o personagem
        objPersonagem.transform.position = posicaoInicial;
        player = objPersonagem.transform;

        //Ajusta a camera
        var camera = FindObjectOfType();
        camera.alvo = objPersonagem.transform;
    }

Buscamos o script da câmera e depois dizemos quem é o alvo ^^

Já podemos até fazer um teste. Volta ao Unity e adiciona o Script GC Camera a Main Camera e informa o valor da velocidade que você quer:

Agora volte a Scene MenuFases e lá no objeto Fase1 diga para ir para a Fase1:

(Estou pensando em mudar isso depois, acrescendo mais um post a esse tutorial. Ensinando a vocês a fazer uma tela de Loading de fases, mas por hora, vamos fazer o botão chamar direto a fase).

Agora volte a Scene Main e faça todo o percurso até chegar na fase e testar sua câmera. Ai já deverá ver que a câmera se move de forma suave. Se a câmera fica muito para trás quando seu personagem anda, aumente a velocidade, assim a porcentagem gerada pela velocidade * Time.deltaTime será maior, o que significa que ele vai estar mais próximo do destino do que da posição de origem ao mover ^^.

Porém, a câmera ainda mostra conteúdos que a gente não quer que seja exibido, não é mesmo? Então precisaremos definir os limites que a câmera pode ir.

Para fazer o limite, bem… eu pesquisei, pesquisei, pesquisei, pesquisei e não achei nenhum script legal para servir de modelo para vocês, então eu mesmo criei o meu modelo de limitação da câmera que acho que seja mais fácil de entender. Mas relaxem, que eu vou desenhar para vocês entenderem e não, não estou zoando, vou desenhar mesmo.
Bom, o grande problema da limitação da câmera, é que dependendo da resolução do pc, o alcance da nossa câmera muda correto?

Porém se você analisar essas duas imagens acima vai ver que o problema é apenas horizontalmente. Verticalmente o alcance da câmera não diminui ou aumenta.

O script que vou explicar, serve apenas para câmera Orthographic, para fazer uma com perspective, terei que pensar em outro script.

Bom, vocês se lembram do Size da nossa Câmera Orthographic

Esse 10 ai que eu usei, nada mais é do que dizer, do ponto central da nossa câmeras, tem 10 posições para cima e 10 posições pra baixo. Ou seja, imaginando que nossa câmera está na posição 0, então ela vai enxergar tudo da Y= 10 a Y = -10. Já o X, vai mudar de acordo com a resolução da pessoa.

No nosso script nós vamos definir as posições limite de X e Y:

Script: GCCamera.cs

using UnityEngine;
using System.Collections;

public class GCCamera : MonoBehaviour {

    public Transform alvo;      //Quem a camera segue
    public float velocidade;    //Com qual velocidade a camera segue

    public float minX = -9999;
    public float maxX = 9999;
    public float minY = -9999;
    public float maxY = 9999;

Eu adicionei os valores 9999 e -9999 como default. É um valor alto, para caso sua scene seja grande, ela dificilmente entre nesse limite, deixando a câmera sem limitações pros lados. Caso a gente queira limitar, então a gente define um valor real, ok?

Bom, se tratando de Y, a gente já viu que nós não temos problema em relação a resolução, então aqui é bem simples. Basta você posicionar a sua camera na parte inferior e superior no Inspector e guardar os valores de Y:

Inferior (Y = 1):

Superior (Y = 14):

Bom, agora no nosso script vamos verificar no método Update após ele ter ser movido, se a camera é do tipo Orthographic. Caso sim, vamos recuperar os valores de X, Y, Z e garantir que eles estejam dentro do limite:

    void Update() {

        if (alvo != null) {
            var destino = new Vector3(alvo.position.x, alvo.position.y, transform.position.z);
            transform.position = Vector3.Lerp(transform.position, destino, velocidade * Time.deltaTime);
        }

        //Limite
        var camera = GetComponent();
        if (camera.orthographic) { 
            var x = transform.position.x;
            var y = transform.position.y;
            var z = transform.position.z;

            x = Mathf.Clamp(x, minX, maxX); 
            y = Mathf.Clamp(y, minY, maxY);

            transform.position = new Vector3(x, y, z);
        }
    }

Após o comentário //Limite, buscamos o Script Camera, e verificamos se ele é orthographic (camera.orthographic == true). Caso sim, recuperas as informações de X, Y e Z da posição da camera. E dizemos que tanto X quanto Y, ele tem que estar dentro do limite informado. Para definir o limite usamos o método Mathf.Clamp, que nada mais faz do que verificar se o valor do primeiro parâmetro é maior que o valor mínimo (segundo parametro) e menor que o valor máximo (terceiro parâmetro). Caso seja menor, então o valor retornado será o valor mínimo, caso seja maior, o valor retornado será o valor máximo. Caso esteja entre os dois, o valor retornar é o informado no primeiro parâmetro.

Exemplo:
Mathf.Clamp(10, 0, 20) = Retorna 10
Mathf.Clamp(-10, 0, 20) = Retorna 0
Mathf.Clamp(30, 0, 20) = Retorna 20

Tranquilo? Com isso só então precisamos dizer que a nova posição da camera com o X e Y atualizados.

Desta forma O Y já deve funcionar com as informações que pegamos antes (Min = 1 e Max = 14), afinal ele é igual para qualquer resolução:

A câmeras não vai exibir nada abaixo do chão e nem acima do background, vai respeitar a posição que informamos antes. O grande problema aqui é o X, pois ele muda conforme a resolução:

Então aqui temos que pegar o valor do alcance horizontal. Já vimos que o alcance Vertical é o mesmo que o Size da camera Orthographic, correto? Então o alcance horizontal vai ser o Size * a resolução da pessoa LARGURA/ALTURA:

var alcanceHorizontal = camera.orthographicSize * Screen.width / Screen.height;

Mas então com isso já sabemos que independente da resolução do jogador, o alcanceHorizontal vai retornar a distância do ponto central da câmera para um dos lados.

Agora pense comigo, se já o alcance horizontal da nossa câmera, para definir a posição dela, é só pegar a posição limite do cenário do lado esquerdo + o alcance horizontal. E a posição limite do lado direito – o alcance horizontal. Vai um desenho ai para vocês entenderem:

Digamos que a gente sabe que a posição limite da nossa camera do lado esquerdo (minX) é 0 e que a posição máxima do limite do lado direito horizontalmente é 80 (maxX). A gente também já descobriu o alcance da nossa camera horizontalmente. Então só precisamos pegar a posição do limite esquerdo + o alcance horizontal para achar a posição correta da camera. Ou seja, se a resolução do jogador for menor, o alcance também será menor, consequentemente a posição da câmera será mais próxima do Limite. Deu para entender? É meio difícil essa parte mesmo, exige um pouco do raciocínio da pessoa. Mas se você não entendeu e não quer entender tudo bem, basta entender que em Y a gente pega a posição da câmera mesmo e X, nós pegamos a posição dos objetos no limite da nossa scene.

Arrumando isso via código ficaria:

Script: GCCamera.cs

    void Update() {

        if (alvo != null) {
            var destino = new Vector3(alvo.position.x, alvo.position.y, transform.position.z);
            transform.position = Vector3.Lerp(transform.position, destino, velocidade * Time.deltaTime);
        }

        //Limite
        var camera = GetComponent();
        if (camera.orthographic) { 
            var x = transform.position.x;
            var y = transform.position.y;
            var z = transform.position.z;

            var alcanceHorizontal = camera.orthographicSize * Screen.width / Screen.height;

            var realMinX = minX + alcanceHorizontal;
            var realMaxX = maxX - alcanceHorizontal;

            x = Mathf.Clamp(x, realMinX, realMaxX); 
            y = Mathf.Clamp(y, minY, maxY);

            transform.position = new Vector3(x, y, z);
        }
    }

Para saber quem é a posição limite dos lados, basta a gente pegar as posições dos objetos LimiteEsquero e LimiteDireito:

Então agora é só adicionar as posições ao script GCCamera:

Pronto, agora já está tudo ok independente da resolução do jogador:

Agora só falta uma besteira para acabar esse tutorial gigante u.u. É um script simples. Que iremos chamar de EventoBoss e o salvaremos dentro de scripts/cenarios, beleza? Esse script é super simples:
Script: EventoBoss.cs

using UnityEngine;
using System.Collections;

public class EventoBoss : MonoBehaviour {

    void OnTriggerExit2D(Collider2D colisor) {
        if (colisor.tag.Equals("Player")) {
            if (colisor.transform.position.x > transform.position.x) {

                var collider = GetComponent();
                collider.isTrigger = false;

                var camera = FindObjectOfType();
                camera.minX = colisor.transform.position.x – 2f;
            }
        }
    }
}

Aqui estamos dizendo que se o personagem cruzar um collider com a opção Is Trigger marcada, esse collider não será mais do tipo Is Trigger, ou seja, o personagem vai bater essa parede invisível sem poder voltar e a camera também não vai poder ir para trás desse collider.

Para isso fazemos duas verificação antes. Se foi realmente o player que passou e se ele passou para o lado direito (a posição dele em X é maior do que a do objeto atual).

O -2f que adiciono junto com a posição do objeto colisor, é apenas para o personagem não ficar colado na tela.
Para por isso em prática, vamos criar um objeto na nossa aba Hierarchy a qual chamarei de LimiteBoss. E nele adicionarei o script EventoBoss e o BoxCollider2D com a opção Is Trigger marcada:

Com isso quando o personagem cruzar esse Box Collider 2D não poderá mais voltar. Isso é o que normalmente os jogos Beat’em Up antigos faziam. Se você quisesse poderia até mesmo adicionar também nesse script uma variável publica para o Audio de uma música só para boss e botava para tocar na câmera.

Bom, agora é só salvar tudo e ficar feliz porque esse tutorial acabou. Ooooh trabalho, viu u.u. E o próximo também será um pouco trabalhoso, pois vamos criar a Interface e a classe abstrata mãe das classes dos inimigos.
Mas por hoje paramos por aqui mesmo. Valeu pessoal e até o próximo post 😉

Carnageddon – Carnaval Z (Mobile)

O carnaval acabou e o ano começou para os brasileiros não é mesmo? Mas e se você ainda puder pular o carnaval? E se você puder pular o carnaval com zumbis!

Leia Mais…

11 – Tutorial Intermediário – Pause

Este tutorial é para tirar a dúvida de algumas pessoas sobre como pausar o jogo. Porém esse é um script tão pequeno que vocês vão se surpreender.

Leia Mais…

99Gamers – Crowdfunding para desenvolvedores indies!

“Carlos com a ajuda dos seus tutoriais eu já consigo dá os primeiros passos no meu jogo, mas ainda é complicado desenvolver um jogo sem ajuda financeira…” Bom, neste caso você precisa conhecer o 99Gamers!

Leia Mais…

10.5 – Tutorial Intermediário – Criando Mapa

E como prometido estamos em mais um tutorial extra! Neste aprenderemos a criar uns mapas legais.

Leia Mais…

Senta que lá vem a história – Jogos para MS-Dos

AOoooooowwww moçada, tudo certo? Hoje resolvi fazer um listão de 10 jogos da época do Pentium 133, HD de 8 Gb, e 256 Mb de ram, acredite esse era um puta PC para games da época do MS-Dos e windows 95, e eu tinha algo parecido com isso ahuahuahuahuaha, então se você quer sentir a nostalgia escorrendo de sua tela, dê um confere nesses super games…

Leia Mais…

10 – Tutorial Intermediário – HUD

Então caros indies? Preparados pra fazer um novo post? O de hoje é bem simples, é só um simples HUD com a contagem de HP, MP e habilidades.

Leia Mais…

09 – Tutorial Intermediário – Salvar e Carregar

E então pessoal, pronto para aprender a salvar e carregar o seu jogo de uma forma diferente?

Leia Mais…

Quinta do Terror – O lado humano – Symphony of the night

Aooooowwwww moçada, que tal uma creepypasta de um dos melhores games já feitos? Castlevania Symphony of the night!

Leia Mais…

Página 6 de 54« Primeira...45678...203040...Última »

Parceiros

Steam Brasil LoboLimão Centro RPG Lab Indie
Mundo Gamer PodTerror

Anunciantes

Aglomerando - Agregador de conteúdo
Uêba - Os Melhores Links GeraLinks - Agregador de links Piadas Idiotas - São idiotas mas o faz rir Tedioso: Os melhores links LinkLog MeusLinks.com - Informação e conteúdo todos os dias para você! Agregador de Links - Madruga Links 4Blogs - Agregador de conteúdo Está no seu momento de descanso né? Entao clique aqui!