Menu

23 – Tutorial Intermediário – Esqueleto

E então indies, preparado para a penúltima parte do nosso tutorial? Bom, já que estamos chegando ao final, então vamos tentar fazer algo mais diferente e usar um inimigo que tenha ataques baseados no ataque quanto na magia!

Então para esse inimigo usaremos o sprite do Skeleton, disponibilizado pelo nosso amado irmirx com suas belas animações:

http://opengameart.org/content/skeleton-animations

Pode pegar todas as imagens, pois estou pensando em fazer esse personagem um pouco mais elaborado. Ou seja uma mistura do Zumbi, da Medusa e do Vampiro.

Então adicionem os sprites numa nova pasta Resources/sprites/inimigos/esqueleto/ da seguinte forma:

andando -> walk
parado -> idle
atacando -> attack
morrendo -> die
surgindo -> appear

01- Tutorial Fase 4 - Inimigo

Próximo passo é criar um objeto na aba Hierarchy com o nome Esqueleto, adicionar o Sprite Renderer com um sprite qualquer do esqueleto para a gente ter a noção do seu tamanho e posição para ajustarmos para as configurações que acharmos melhor:

02- Tutorial Fase 4 - Inimigo

Então adicione o Box Collider 2D e o Rigidbody2D com a opção Freeze Rotation marcadada e o Sleeping Mode como Never Sleep, ao seu Esqueleto.

20- Tutorial Fase 4 - Inimigo

Pronto, já ajustou o tamanho e a posição do seu inimigo, certo? Então vamos criar as animações. Clique sobre o personagem na aba Hierarchy e vá à aba Animation criando as animações dentro da pasta Resources/animations/inimigos/esqueleto: escondido (Sem Loop Time), surgindo (Sem Loop Time), parado, andando, atacando (Sem Loop Time), morrendo (Sem Loop Time).

Na animação escondido não terá nenhum sprite.

Na animação surgindo terá os sprites surgindo. Só que eles ficam um pouco mais alto em relação aos demais sprites:

04- Tutorial Fase 4 - Inimigo

Então, selecione todos os sprites que fazem o personagem subi, e no pivot troque para custom e altere o valor de Y para 0.56:

06- Tutorial Fase 4 - Inimigo

Nas animações parado, andando e morrendo basta por os sprites do inimigo sem alterar nada, eles já estão ok.

Após adicionar os sprites do ataque na animação atacando, vai ver que ele também precisa de um ajuste:

07- Tutorial Fase 4 - Inimigo

Então selecione todos os sprites na pasta Project e no Inspector troque o Pivot para Custo com os dados X = 0.7 e Y 0.53:

08- Tutorial Fase 4 - Inimigo

Com isso nossas animações já devem estar prontas. Então vamos para a animator! Nela vamos criar os parâmetros:

surgiu -> trigger
morreu -> trigger
atacou -> trigger
movimento -> bool

13- Tutorial Fase 4 - Inimigo

As transições serão:

Entry -> escondido
escondido -> surgindo (Condição: surgiu | Has Exit Time: Não | Transition Duration: 0)
surgindo -> parado (Condição: nada | Has Exit Time: Sim | Transition Duration: 0)
parado -> andando (Condição: movimento == true | Has Exit Time: Não | Transition Duration: 0)

14- Tutorial Fase 4 - Inimigo

andando -> parado (Condição: movimento == false | Has Exit Time: Não | Transition Duration: 0)
parado -> atacando (Condição: atacou | Has Exit Time: Não | Transition Duration: 0)
andando -> atacando (Condição: atacou | Has Exit Time: Não | Transition Duration: 0)
atacando -> andando (Condição: nada | Has Exit Time: Sim | Transition Duration: 0)
Any State -> morrendo (Condição: morreu | Has Exit Time: Não | Transition Duration: 0)

12- Tutorial Fase 4 - Inimigo

Já montamos a estrutura do nosso querido esqueleto. Neste caso pode tirar lá o sprite dele no Sprite Renderer para que ele comece invisível.

21- Tutorial Fase 4 - Inimigo

Agora só falta criar seu script! Então bora lá criar um script para o nosso esqueleto!

Criem um novo script chamado Esqueleto dentro da pasta scripts/inimigos. Esse script vai herdar de Inimigo, então sua estrutura será:

Script: Esqueleto.cs

using UnityEngine;
using System.Collections;
using System;

public class Esqueleto : Inimigo {

    protected override void atacar() {
        
    }

    protected override void mover() {
        
    }
}

A primeira coisa que a gente vai fazer logo é definir primeiro o status do personagem no método Awake:

Script: Esqueleto.cs

    protected override void Awake() {
        base.Awake();
        status = new Status(30, 10, 5); //HP = 30 | MP = 10 | Ataque = 5
    }

Tá e agora, o que esse script terá diferente? Qual será a IA desse esqueleto?

Bom, primeiro bora para o ataque magico. Aqui a ideia é que ele solte aquela magia negra CASO:

1 – Não esteja atacando;
2 – possua MP suficiente;
3 – O personagem esteja próximo de uma distância X;
4 – O Esqueleto não esteja encostado no personagem (Afinal se ele estiver encostado, ele vai utilizar o ataque normal).

Por hora não vou colocar tempo de intervalo entre um ataque e outro, para os ataques serem lançados rápidos mesmo, de forma que a tática para enfrenta-lo seja fazer ele gastar toda sua MP antes de tentar passar por ele.

Então vamos ter que ter uma coisas em mente. Para calcular se um personagem está dentro da distância podemos fazer de duas formas:

1 – Pegar a posição X do personagem e do Esqueleto e subtrair. Se o valor absoluto for igual ou menor que o alcance, então está dentro da área de ataque;
2 – Usar o Raycast que vimos no Vampiro. Eu particularmente prefiro essa!

Quanto as variáveis, vamos precisar saber para qual lado o esqueleto está virado e o alcance do ataque:

Script: Esqueleto.cs

    public float alcanceAtaque;
    public bool direita;

Agora no ataque vamos criar as verificações:

Script: Esqueleto.cs

    protected override void atacar() {
        //Saber se está proximo
        var direcao = (direita ? Vector2.right : -Vector2.right);
        Debug.DrawRay(transform.position, direcao * alcanceAtaque, Color.red);
        var proximo = Physics2D.Raycast(transform.position, direcao, alcanceAtaque, 1 << LayerMask.NameToLayer("Personagem"));
        
        //Saber se está atacando
        var atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");

        //Saber se tem MP suficiente
        var temMP = status.getMP() >= 1; //Usamos 1 de MP por ataque
   }

Para o alcance, verificamos se tem algum objeto com a layer Personagem dentro do alcance informado e na direção que o esqueleto está virado.

Depois buscamos saber se o esqueleto não está atacando através do animator.

Por fim verificamos tem o esqueleto tem MP suficiente, levando em consideração que cada ataque mágico vá lhe custar 1MP.

Ainda tem a verificação se ele está ou não encostado, mas isso já é feito automaticamente lá no script Inimigo nos OnColliders, lembram?

Então tendo essas informações em mão é só trazer um if que verifique se está próximo, se não está atacando, se tem MP e se não está encostado. Caso essas 4 condições sejam verdadeiras, então podemos buscar o prefab da magia negra e a invocar na mesma posição do Esqueleto, para então reduzir o custo da magia e chamamos a animação de ataque!

Script: Esqueleto.cs

    protected override void atacar() {
        //Saber se está proximo
        var direcao = (direita ? Vector2.right : -Vector2.right);
        Debug.DrawRay(transform.position, direcao * alcanceAtaque, Color.red);
        var proximo = Physics2D.Raycast(transform.position, direcao, alcanceAtaque, 1 << LayerMask.NameToLayer("Personagem"));
        
        //Saber se está atacando
        var atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");

        //Saber se tem MP suficiente
        var temMP = status.getMP() >= 1; //Usamos 1 de MP por ataque
        
        if (proximo && !atacando && temMP && !encostado) {
            var prefab = Resources.Load("prefabs/inimigos/MagiaNegra"); //Prefab da Magia
            Instantiate(prefab, transform.position, Quaternion.identity);
            status.usaMagia(1); //Custo da Magia	
            animator.SetTrigger("atacou");
        }
    }

E com isso já temos 2 ataques. Esse que acabamos de fazer baseado na magia e outro baseado no ataque físico ao encostar o personagem.

Por fim só precisamos agora cuidar da sua movimentação. Para a movimentação também vai ser um pouco diferente. Aqui nosso esqueleto vai andar em direção ao player caso ele esteja dentro do alcance da visão do inimigo. E também precisamos nos preocupar para não mover enquanto ataca. Então além da variável direita que já temos e que define a direção do esqueleto, vamos também precisar saber a velocidade com que ele vai andar e o alcance da visão do inimigo:

Script: Esqueleto.cs

    public float alcanceAtaque;
    public bool direita;
    public float alcanceVisao;
    public float velocidade;

Bom, agora é a vez do método mover. Nele primeiro verificamos se não está atacando. Se tiver nem movemos o esqueleto. Caso não esteja atacando, vamos verificar a direção que o personagem está em relação ao esqueleto, se está para direita ou esquerda, para assim girar nosso esqueleto para o lado correto. Então verificamos se o personagem está dentro do alcance da visão do esqueleto, caso esteja iremos mover o esqueleto e passar essa informação também para o animator:

Script: Esqueleto.cs

    protected override void mover() {
        var atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");

        if (!atacando) {
            //Direção do esqueleto
            var personagem = GameObject.FindGameObjectWithTag("Player");
            var direcaoPlayer = personagem.transform.position.x - transform.position.x;

            if (direcaoPlayer > 0 && !direita) {
                direita = true;
                inverter();
            }

            if (direcaoPlayer < 0 && direita) {
                direita = false;
                inverter();
            }

            //Alcance
            var direcao = (direita ? Vector2.right : -Vector2.right);
            var vendo = Physics2D.Raycast(transform.position, direcao, alcanceVisao, 1 << LayerMask.NameToLayer("Personagem"));
            Debug.DrawRay(transform.position, alcanceVisao * direcao, Color. yellow);
            if (vendo) 
                transform.Translate(direcao * velocidade * Time.deltaTime);

            animator.SetBool("movimento", vendo);
        } 
    }

Vamos entender o código agora.

1 – Primeiro verificamos se o esqueleto não está atacando (verificando se a animação atacando é a que está sendo executada)
Caso não esteja atacando:
2 – Buscamos o Objeto com a Tag Player na scene.
3 – Descobrimos a direção do player em relação ao nosso inimigo no eixo X. Se a direção for negativa então, está a esquerda. Se for positiva está a direita. Ai vai uma imagem para ajudar a quem não entendeu direito:

16- Tutorial Fase 4 - Inimigo

4 – Então se a direcaoPlayer for maior que zero e o esqueleto não tiver para direita, então o invertemos para direita
5 – Caso a direcaoPlayer seja negativa e o esqueleto não esteja para a esquerda, invertemos ele para esquerda.
Em relação ao alcance
6 – Vemos se o alcance deve buscar para direita (Vector2.right) ou para esquerda (-Vector2.right), dependendo da direcao;
7 – Verificamos se tem algum objeto com a Layer Personagem dentro do alcance da visão através do método Physics2D.Raycast e usamos o Debug.DrawRay para nos ajudar a visualizar lá na Scene com uma linha amarela.
8 – Caso o personagem esteja no alcance da visão do esqueleto, fazemos o movimento do esqueleto para direção do player na velocidade declarada.
9 – Por fim, informamos ao animator se o esqueleto está ou não em movimento (Se tiver vendo, ele vai estar em movimento, se não tiver vendo, ele não estará em movimento).
Com isso nosso script do esqueleto já está pronto. Só nos restar voltar ao editor do Unity e adicionar o script ao esqueleto, informando os dados necessários:

17- Tutorial Fase 4 - Inimigo

Por fim, transforme o Esqueleto em um prefab (Pasta Resources/prefabs/inimigos) e teste o jogo desde o início (Scene Main).

Quando tiver testando, caso tenha adicionando os Debug.DrawRay, poderá ver o alcance do ataque (Linha vermelha) e da visão (Linha amarela):

18- Tutorial Fase 4 - Inimigo

Se ele entrar na linha amarela, já irá andar em direção ao personagem e caso entre na linha vermelha, o esqueleto ficará atacando o jogador com sua mágia.

19- Tutorial Fase 4 - Inimigo

E assim terminamos mais um post! Espero que tenham curtido e qualquer dúvida é só deixar nos comentários 😉

Criador do Jogos Indie, amante de jogos, terror, música, anime e programação. Estudante de mestrado com foco em jogos na educação. Louco por Resident Evil e... sei lá, acho que é isso O.o

One comment

  1. Muito legal esse tutorial. A inteligencia ficou bem boa.

Deixe uma resposta

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!