Menu

14 – Tutorial Intermediário – Boss Andromalius

E hoje vamos trabalhar com a criação do nosso primeiro Boss. Ele na realidade não será difícil, como disse antes é bem parecido com o Zumbi, porém além dos movimentos horizontais também haverá os movimentos verticais.

Ah, só uma coisa, a dificuldade do chefe que o jogador terá ao enfrenta-lo não tem relação alguma com o nosso tutorial, ok? Aqui apenas vou apresentar formas diferentes de criar inimigos, talvez o segundo chefe seja bem mais difícil do que o ultimo e por ai vai. A ideia é apenas criar conteúdos diferentes para os cenários, inimigos e boss.

Bom, nós já temos a estrutura padrão do nosso inimigo através da classe abstrata Inimigo, correto? Então aqui é só criar um script (C#) para o nosso boss chamado Andromalius dentro da pasta scripts/inimigos.

Nele assim como foi com o script de zumbi vamos determinar a velocidade, a direção direita, minX, maxX, porém além disso, também vamos verificar se o inimigo está subindo ou descendo, então entrará outras 3 variaveis: subindo, minY,maxY:

Script: Andromalius.cs

    public bool direita;
    public bool subindo;
    public float velocidade;
    public float minX;
    public float maxX;
    public float minY;
    public float maxY;

Qual é a próxima coisa a ser feita? Hã? Hã? Ora, ora, vão dizer que já esqueceram? É definir os pontos de vida e o ataque do boss no método Awake:

Script: Andromalius.cs

    protected override void Awake() {
        base.Awake(); //Chama o Awake da classe Inimigo
        status = new Status(30, 0, 7); //HP = 30 | MP = 0 | Ataque = 7

        if (!direita) 
            inverter();
    }

Nele defini os pontos de vida do inimigo sendo 30 e seu ataque igual a 7. Se o inimigo não estiver para direita, a gente já muda o seu sprite (O sprite original o inimigo é virado para a direita, mas se quiser inverter apenas o sprite, poderia usar opção Flip que tem no Sprite Renderer).

Em relação a subindo, não tem nada, porque o sprite não vai mudar independente de estar subindo ou descendo).

Agora, vamos para o movimento. O movimento horizontal é praticamente o mesmo do zumbi sem tirar e nem por, mas que tal a gente fazer de uma forma diferente? Sim, ao invés de fazer ele andar horizontalmente e depois vertical no script como faríamos se fossemos fazer igual ao Zumbi, podemos fazer ele já ir diagonalmente, o que acham? Para mudar um pouco esse script, diminuir seu tamanho a percebemos coisas que talvez não perceberiam (Embora seja muito claro isso que a gente vai fazer), bom o primeiro é criar uma variável que vai armazenar a direção que nosso boss irá se mover:

Script: Andromalius.cs

   protected override void mover() {
        var direcao = new Vector3();
   }

Depois é verificar se o personagem passou dos limites horizontalmente ou verticalmente:

Script: Andromalius.cs

    protected override void mover() {
        var direcao = new Vector3();

        //Horizontal
        if (direita) {
            if (transform.position.x > maxX) {  //Passou do limite da direita
                inverter();
                direita = false;
            }
        } else {
            if (transform.position.x < minX) { //Passou do limite da esquerda 
                inverter(); 
                direita = true;
            }
        }
        //vertical
        if (subindo) { 
            if (transform.position.y > maxY)
                subindo = false;
        } else {
            if (transform.position.y << minY)
                subindo = true;
        }
    }

Bom, agora já sabemos se ele está subindo ou descendo. É a vez de mudar os valores de x e y da variável direção. E iremos fazer isso apenas com uma linha! Isso que eu vou mostrar é uma forma resumida de fazer um IF para atribuir valor, usado na maioria das linguagens que herdam as características da linguagem C. A estrutura é essa abaixo:

(CONDICAO ? SE VERDADE RETORNA ESSE VALOR : SE FALSO RETORNA ESSE VALOR)

Primeiro vem uma condição booleana (Ou seja True ou False) , seguida de uma interrogação ”?”. Caso Seja verdade, ela vai retornar o primeiro valor após a interrogação. Caso seja falso, o valor retornado será o que fica após os dois pontos “:”. Então nosso código pode ficar assim:

        direcao.x = (direita ? 1 : -1);
        direcao.y = (subindo ? 1 : -1);

Caso ele esteja para direita, o x da direção vai receber 1. Caso não esteja vai receber -1. O mesmo vale para o y, caso esteja subindo, vai receber 1 e caso não esteja subindo vai receber -1.

Assim a nossa direção será nas diagonais:

direcao = (1, 1, 0) = Nordeste
direcao = (1, -1, 0) = Noroeste
direcao = (-1, 1, 0) = Sudeste
direcao = (-1, -1, 0) = Sudoeste

direcoes

Por só precisamos aplicar a direção no nosso método Translate com a velocidade e o regulador Time.deltaTime:

Script: Andromalius.cs

    protected override void mover() {
        var direcao = new Vector3();

        //Horizontal
        if (direita) {
            if (transform.position.x > maxX) {  //Passou do limite da direita
                inverter();
                direita = false;
            }
        } else {
            if (transform.position.x < minX) { //Passou do limite da esquerda
                inverter(); 
                direita = true; 
            }
        }
        //vertical 
        if (subindo) { 
            if (transform.position.y > maxY)
                subindo = false;
        } else {
            if (transform.position.y < minY)
                subindo = true;
        }

        direcao.x = (direita ? 1 : -1);
        direcao.y = (subindo ? 1 : -1);

        transform.Translate(direcao * velocidade * Time.deltaTime);
    }

Pronto, já está com a direção definida. Agora só falta a gente fazer com que quando o nosso boss Andromalius acerte o inimigo, cause dano, igualzinho o método OnCollisionStay2D do Zumbi:

Script: Andromalius.cs

    void OnCollisionStay2D(Collision2D colisor) {
        if (colisor.gameObject.tag.Equals("Player") && !status.estaMorto()) {
            var personagem = colisor.gameObject.GetComponent();
            personagem.recebeDano(status.getAtaque());
            animator.SetTrigger("atacou");
        }
    }

E com isso terminamos o script bem simples do primeiro Boss (Relaxe, que os próximos boss, vão ter coisas diferentes, quis começar com algo light mesmo):

Script: Andromalius.cs

using UnityEngine;
using System.Collections;
using System;

public class Zumbi : Inimigo {

    public bool direita;
    public float velocidade;
    public float minX;
    public float maxX;

    protected override void Awake() {
        base.Awake(); //Chama o Awake da classe Inimigo
        status = new Status(10, 0, 5); //HP = 10 | MP = 0 | Ataque = 5

        if (direita)
            inverter();

        
    }

    protected override void atacar() {}

    protected override void mover() {
        if (direita) {
            transform.Translate(Vector3.right * velocidade * Time.deltaTime); //Anda para direita

            if (transform.position.x > maxX) {  //Passou do limite da direita
                inverter();
                direita = false;
            }
        }
        else {
            transform.Translate(-Vector3.right * velocidade * Time.deltaTime); //Anda para esquerda

            if (transform.position.x < minX) { //Passou do limite da esquerda
                inverter();
                direita = true;
            }
        }
    }

    void OnCollisionStay2D(Collision2D colisor) {
        if (colisor.gameObject.tag.Equals("Player") && !status.estaMorto()) {
            var personagem = colisor.gameObject.GetComponent();
            personagem.recebeDano(status.getAtaque());
            animator.SetTrigger("atacou");
        }
    }
}

Em relação aos sprites, estou pensando em usar o sprites do Andromalius disponibilizado gratuitamente no site OpenGameArt pelo Balmer:

http://opengameart.org/content/bosses-and-monsters-spritesheets-ars-notoria

É aquela cabeça voadora que mais lembra a Medusa do que o próprio Andromalius. Aproveitem e baixem logo todos os sprites, pois 3 dos nossos 4 bosses estão ai (Iremos usar as três formas do Harlequin e o Blue Mage/Discipline em bosses futuros).

Após baixar adicionem o sprite andromalius-57x88 (renomeiem para apenas andromalius) na pasta Resources/sprites/inimigos/andromalius. Caso você não tenha visto o tutorial básico (Coisa feia u.u), vamos ver como a gente trabalha com multisprites. Então tratem de colocar o Texture Type para Sprite e o Sprite Mode para Multiple:

01- Tutorial Fase 1 Boss

Depois dê um Apply lá embaixo e vão na opção Sprite Editor:

02- Tutorial Fase 1 Boss

Nesta tela que vai abrir é onde a gente pode cortar nossos sprites.

Podemos fazer isso de várias formas como clicando e arrastando:

03- Tutorial Fase 1 Boss

Ou através das 3 opções lá no Slice:

04- Tutorial Fase 1 Boss

O Automatic é bem legal, ele tenta identificar sozinho os formatos e corta para você. O Grid By Cell Size você define o tamanho da altura e largura dos sprites para ele cortar (E também define o espaçamento entre um sprite e outro). O Grid By Cell Count ele corta baseado no número de linhas e colunas e se vocês reparem na imagem, ela já veio certinho centralizada em 3 linhas e 8 colunas. Então Grid By Cell Count é a melhor opção para a gente:

05- Tutorial Fase 1 Boss

Depois de definir as colunas (C) e as linhas (R), basta dá um Slice e ver a mágica acontecer:

06- Tutorial Fase 1 Boss

Não sei se vocês conseguem ver, mas surgiu umas linhas ai que define os limites dos sprites cortados. Depois é só clicar fechar e confirmar o slice ou clicar no Apply:

07- Tutorial Fase 1 Boss

Pronto, nossa imagem que era única, já foi partida em várias outras:

08- Tutorial Fase 1 Boss

Show!

Então é a hora de criar um objeto com o nome Andromalius (De preferência já na Scene que o usaremos) e criar as animações na pasta Resources/animations/inimigos/andromalius:

09- Tutorial Fase 1 Boss

11- Tutorial Fase 1 Boss

E não, a primeira animação Escondido não será vazia! Ela vai ter o sprite andromalius_0, só que invertido no eixo X. Para inverter, vocês podem marcar a opção Flip X no Sprite Renderer, que a imagem será invertida horizontalmente (Ou já use direto o Andromalius_16, sem dar arrodeio):

andromalius

Para a animação surgindo, podemos usar os sprites na ordem:

Andromalius_16
Andromalius_17
Andromalius_20
Andromalius_21
Andromalius_22
Andromalius_23
Andromalius_18
Andromalius_19

12- Tutorial Fase 1 Boss

Para o andando usamos o do andromalius_0 ao andromalius_7.

Para atacando usamos do andromalius_8 ao andromalius_15 (Só muda a boca aberta dele).

Para o morrendo, iremos adicionar apenas o sprite andromalius_0 três vezes:

13- Tutorial Fase 1 Boss

Clicando sobre o segundo keyframe (O segundo sprite) e se garantindo agora que a opção Record, esteja selecionada:

14- Tutorial Fase 1 Boss

Você irá na aba Inspector e mudar a cor do Sprite para preto:

15- Tutorial Fase 1 Boss

Reparem que lá na aba Animation surgiu uma nova linha para as modificações feitas no SpriteRenderer.color saindo o keyframe1 para o keyframe2:

16- Tutorial Fase 1 Boss

Isso significa que a mudança vai ocorrer gradativamente do 1 para o 2. Caso a alteração já fosse direto no keyframe três, a mudança ia ocorrer gradativamente do keyframe 1 para o keyframe 3.

Agora clique no KeyFrame 3 e altere o Alpha para zero:

17- Tutorial Fase 1 Boss

Caso estenda aquela segunda linha lá na aba animação poderá ver as mudanças ocorrendo na colocação e no channel alpha:

18- Tutorial Fase 1 Boss

E dai já podemos perceber que ele já vai começar a ficar transparente do primeiro keyframe e ficará totalmente transparente no ultimo. Caso você queira que ele só comece a ficar transparente a partir do segundo keyframe quando ele já fica totamente preto. É só clicar no primeiro keyframe do Color.a e arrastar para a segunda posição:

19- Tutorial Fase 1 Boss

Prontinho. Nosso boss ao morrer ele vai ficar primeiro todo preto até o segundo keyframe, para só então começar a desaparecer !

Agora precisamos trabalhar o Animator, então vão à aba Animator e aqui será a mesma coisa do Zumbi. Iremos criar 3 Triggers:

23- Tutorial Fase 1 Boss

A animação inicial será a “escondido” (Que nem é escondido pensando bem, já que ele já está lá esperando o player O.o) a primeira animação, depois as transições das nossas animações serão:

escondido -> surgindo (Condição: surgiu | Has Exit Time: Não | Transition Duration: 0)
surgindo -> andando (Condição: nada | Has Exit Time: Sim | 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)

Acho que não esqueci nada O.o

25- Tutorial Fase 1 Boss

Bom, agora você pode adicionar um prefab do player para comparar o seu tamanho e o aumentar, caso não queira que seu boss fique parecendo uma mosca:

20- Tutorial Fase 1 Boss

21- Tutorial Fase 1 Boss

(É a imagem é muito pequena e fica meio pixelizada quando a aumentamos e nem combina com o sprites do cenário e personagem, mas é o que temos para hoje. Por isso que nunca menospreze um artista, eles tem um papel super importante!)
O próximo passo agora é adicionar um Circle Collider 2D:


22- Tutorial Fase 1 Boss

Então adicionamos o Rigidbody2D para os ataques que não possuem Rigidbody2D conseguirem acertar o Boss (A colisão só acontece se pelo menos um dos dois tiver o Rigibody2D). Porém marquem a opção Is Kinematic, para que a física não faça nosso Boss cair (Ele voa).

26- Tutorial Fase 1 Boss

Então o ultimo passo é adicionar o script junto com os dados e posição do boss:

27- Tutorial Fase 1 Boss

Não se esqueçam do Animator, ok?

Bom, feito isso já pode testar seu jogo. Salve tudo e volta a Scene Main e teste.

28- Tutorial Fase 1 Boss

29- Tutorial Fase 1 Boss

Estando tudo certo, crie o prefab do seu boss.

[[[[[ FASE BONUS DO POST]]]]]

Eu estava aqui pensando se alguém iria perguntar por que os inimigos não sofrem dano quando eles ainda não surgiram...

30- Tutorial Fase 1 Boss

Reparem que as kunais passam pelo colliders do zumbi e passam sem acontecer absolutamente nada. Se quiser pode por até um por um Debug.Log(“teste”) dentro do OnTriggerEnter2D do AtaqueAndante e verá que nem por lá ele passa. Mas se o personagem tiver andando, o dano acontece:

31- Tutorial Fase 1 Boss

E ai, saberia me responder essa? Na realidade isso ficou na minha cabeça por muito tempo quando me deparei com isso pela primeira vez e não achei nada, procurei nos fóruns no Unity por erros parecidos e nenhuma resposta legal. Mesmo que isso seja o que nós queremos, que o inimigo não receba dando enquanto não está ativo, aquilo estava me corroendo por dentro, não saber como aquilo estava funcionando.

Até que depois de várias tentativas descobri que o OnTrigger e OnCollision não funcionavam apenas quando o inimigo estava parado, sem se mover. E lá se foi mais alguns minutos tentando descobrir onde estava a configuração do Unity que desabilitava os Colliders quando um objeto não está se movendo, até que achei o Sleeping Mode no Rigidbody2D:

32- Tutorial Fase 1 Boss

Quando seu personagem não se move, está parado, o Rigidbody2D é desabilitado entrando no modo Sleep até que ele volte a se mover. E sem Rigidbody2D também não existe colisão. Se quiser que isso não ocorra (Como será com o nosso segundo boss, que não se move), deixa a opção Never Sleep selecionada ao invés do Star Awake. Mas para esses dois inimigos, o ideal é que fique essa configuração padrão mesmo.

[[[[[FIM DA FASE BONUS DO POST]]]]]

Bom, seu boss já está ok. Já fez o prefab dele e tudo mais. Então só falta uma coisa. Após derrotar o inimigo completar a fase.

Essa é bem simples. Só precisamos ir no Script GCFase e adicionar uma nova variável que representa o boss:

Script: GCFase.cs

    public GameObject boss;

Agora no método Update vamos verificar se o boss existe. Caso ele não exista (Seja igual a null, ou seja, já foi destruído), chamamos o método finalizarFase();

Script: GCFase.cs

    void Update() {
        if (boss == null)
            finalizarFase();
    }

Esse método, o criamos se não me engano no post da criação do cenário.

Agora é só voltar ao editor do Unity e no objeto GC com o script GCFase, dizer quem é o boss:

33- Tutorial Fase 1 Boss

E com isso quando o Boss for destruído, ele voltar para a fase de seleção de menu, liberando a próxima fase e salvando a atualização no GameStatus!

E com isso terminamos mais um tutorial! Ah e desculpe se ficou um tanto sério a postagem ou direta. É que estou cansado e com a cabeça cheia, mas ainda sim não poderia deixa-los na mão ^^

Qualquer dúvida, já sabem aonde deixar.

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

4 comments

  1. Paulo disse:

    Força ai Carlos estou gostando, ainda não tinha comentado mas tenho seguido todos os tutos. Parabéns….

  2. Natalie Ribeiro disse:

    Oi Carlos tudo bem? Obrigada pelo tutorial.
    Eu estou tento um certo problema nessa parte pois o meu Boss não se mexe, se eu encosto nele eu recebo o dano, ele muda de animação e tudo mais, mas ele simplesmente nao se mexa, ja olhei o codigo e ta igualzinho ao seu, tem ideia do que possa ser?

    • Opa Natalie, se o código realmente está igual, então o problema pode estar em alguma configuração do Unity, como não ter definido velocidade ou a distância (O que acho mais provavel) para identificar o personagem e se mover.

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!