Menu

02 -Tutorial Intermediário – Criando Personagem – Parte 1

E aê, meus indies, tudo joia? Hoje vamos continuar com o nosso tutorial revisando como fazer as animações do personagem criando o script do personagem masculino. Então a brincadeira de hoje será basicamente:

1 – Criar as animações;
2 – Atualizar o script Jogador para modificar as animações;
3 – Criar o script do personagem.

Hoje já será algo bem mais divertido que a aula passada, então vamos deixar de enrolação e ir abrindo logo o Unity!
A primeira coisa que vamos fazer é criar a pasta sprites. Dentro dela vamos criar outra pasta chamada “personagens”, e dentro dessa segunda pasta, vamos criar uma chamada personagem1:

01- Tutorial Personagem 1 -

02- Tutorial Personagem 1 -

Na pasta sprites ficam todas as nossas imagens de personagens, ataques e essas coisas. O Sprite nada mais é do que uma imagem que vemos em um frame. E a animação nada mais é do que várias imagens sendo executadas por segundo. É tipo aqueles desenhos que o pessoa faz em caderno, tipo isso aqui:

Ou seja, cada página seria como se fosse um sprite e a animação é feita passando esses sprites.

A pasta personagens terá duas pastas no total, personagem1 e personagem2 (Afinal vamos ter uma personagem masculino e uma personagem feminina), caso você tivesse outros personagens, ia adicionando nessa pasta para ficar mais organizado.

E dentro de cada pasta dos sprites dos personagens, vão ter outras pastas que definem os sprites de cada tipo de animação. No nosso caso vamos fazer as pastas:

Parado
• Andando
• Pulando
• Atacando
• Morrendo

03- Tutorial Personagem 1 -

Os sprites que eu vou utilizar serão 0800 do site Game Art 2D:

Link do site 

Link para download

Após baixarem e descompactar a pasta com os sprites, vamos arrastar as imagens que queremos para a pasta correspondente dentro do seu Project no Unity:

1 – Seleciona:

04- Tutorial Personagem 1 -

2 – Arrasta:

05- Tutorial Personagem 1 -

3 – Solta:

06- Tutorial Personagem 1 -

Você fará o mesmo processo para os demais sprites:

Andando -> Run
Atacando -> Attack
Morrendo -> Dead
Pulando -> Jump

Tudo tranquilo até então? Bom, agora você vai ver se o Unity importou o conteúdo como sprite ou como textura. Caso tenha sido como textura como foi o meu caso, você vai mudar a opção Texture Type de Texture para Sprite (2D and UI):

07- Tutorial Personagem 1 -

Por fim, clica em Apply lá embaixo:

08- Tutorial Personagem 1 -

No tutorial passado (básico), eu ensinei a criar animações usando apenas uma única imagem com vários sprites, que seria o Sprite Mode multiple, mas nesse caso a nossa imagem só tem um único Sprite, então a opção é Sprite Mode Single mesmo. Caso queira ver como é com múltiplos sprites numa única imagem, dá um pulo lá no tutorial básico. 😉

Agora você terá que fazer isso em todas as imagens caso estejam como textura. Você pode selecionar mais de uma para ser mais rápido:

09- Tutorial Personagem 1 -

Com todos os nossos sprites prontos, agora é a hora de criar o objeto que será nosso personagem. Então vai lá no menu GameObject e pede a opção Create Empty.

10- Tutorial Personagem 1 -

Ou clica com o botão direito na aba Hierarchy:

11- Tutorial Personagem 1 -

Pronto. O nosso objeto receberá o nome Personagem1:

12- Tutorial Personagem 1 -

Após isso vamos adicionar na aba Inspector (Com o objeto Personagem1 selecionado na aba Hierarchy) a Tag “Player” para o Personagem1, assim independente do nome do nosso objeto, podemos encontrá-lo e identificá-lo pela sua tag:

13- Tutorial Personagem 1 -

Bom, o próximo passo é adicionar o Sprite do personagem parado ao nosso Personagem1. Para isso ainda na aba Inspector vá na opção “Add Component” e procure pela opção Sprite Renderer:

14- Tutorial Personagem 1 -

1 – Formar 1 de buscar – Digitando o nome Sprite Render:

15- Tutorial Personagem 1 -

2 – Forma 2 de buscar – Indo na opção Rendering e depois escolhendo Sprite Render:

16- Tutorial Personagem 1 -

17- Tutorial Personagem 1 -

Uma vez adicionado, lá na opção Sprite dentro do Sprite Renderer, vamos seleciona o primeiro sprite do nosso personagem parado:

18- Tutorial Personagem 1 -

19- Tutorial Personagem 1 -

E ele já está ali do lado nas abas Scene e Game, porém parado sem animação, então vamos anima-lo! Mas antes, crie umas pastas no seu Project sendo: animations >> personagens >> personagem1:

20- Tutorial Personagem 1 -

Pronto, agora sim, ainda com o Personagem1 selecionado na aba Hierarchy, vá na aba Animation (Caso, ela não esteja aparecendo, vá lá no menu do topo opção Window >> Animation).

21- Tutorial Personagem 1 -

Terá a opção para você criar uma animação. Então basta clicar. Ele vai pedir para você salvar a animação em algum canto. Vamos por justamente na pasta que acabamos de criar: animations>>personagens>>personagem1 com o nome parado:

22- Tutorial Personagem 1 -

Uma vez salvo, você já poderá arrastar os conteúdos da sua pasta Project para aqui dentro. Então vamos fazer isso com todos os Idle_00*:

23- Tutorial Personagem 1 -

Você já pode ver a sua animação clicando no play ali ao lado:

24- Tutorial Personagem 1 -

É muito provável que a animação vá estar super rápida, então na opção Sample, você pode diminuir essa velocidade para 10 por exemplo:

25- Tutorial Personagem 1 -

Pronto, nossa primeira animação está feita. Agora vamos ali ao lado da opção Sample e pedir para criar mais outra animação:

26- Tutorial Personagem 1 -

Vamos fazer o mesmo procedimento que fizemos agora para as animações morrendo, andando, atacando e pulando. No final essa será a lista de nossas animações:

27- Tutorial Personagem 1 -

O próximo passo agora é a gente pensar. Quais dessas animações são continuas e quais devem parar quando chegarem ao ultimo frame.

Andando e Parado – A animação vai ser continuar, ao chegar no ultimo keyframe, volta para o primeiro, correto?
Morrendo, Pulando e Atacando – Não faz sentido ele volta para o primeiro keyframe, após completar o primeiro ciclo de animação. Então bora procurar por elas na aba Project e remover o loop:

28- Tutorial Personagem 1 -

Após selecionar as três animações e desmarcar a opção Loop Time, temos agora que ir na aba Animator (Ainda com o Personagem1 na aba Hierarchy selecionado), para definir quando cada animação será executada.

Na nossa aba Animator será exibida todas as animações que aquele objeto possui:

29- Tutorial Personagem 1 -

Entry -> Significa que é o inicio, ou seja, indica qual é a primeira animação que será executada. Você pode defini-la clicando com o botão direito na animação e seleciona a opção Set as Layer Default State

30- Tutorial Personagem 1 -

A opção Any State, permite criar uma chamada para outra animação, não importando em qual a animação o objeto esteja. Por exemplo, a animação andando só vai poder vir de parado ou pulando, já animação morrendo se quisermos podemos fazer ela vir de qualquer animação (vai ficar meio estranho ele morrendo no céu, mas é apenas um exemplo), então criamos uma transição vinda de Any State.

Tá, e o que é que define quando uma animação deve mudar para outra? O que define é justamente os parâmetros e transições. Parâmetros são como as variáveis das nossas classes e as transições são as condições necessárias para isso ocorrer.

Vamos criar algumas e vocês já vão começar a entender. Vamos primeira na aba Parameters dentro da aba Animator:

31- Tutorial Personagem 1 -

E em seguida clique no + abaixo do olho, para criarmos nossos parâmetros:

32- Tutorial Personagem 1 -

O primeiro que vamos criar é do tipo Float (Números com valores decimais) e darei o nome velocidade:

33- Tutorial Personagem 1 -

Depois vou criar um parâmetro do tipo Bool (True ou False) estaNoChao:

34- Tutorial Personagem 1 -

Por fim vou criar mais dois do tipo Trigger (Apenas faz uma chamada):

35- Tutorial Personagem 1 -

37- Tutorial Personagem 1 -

Você sabe o que é Trigger? Trigger é como se fosse um gatilho ou podemos ir até além, um botão, que quando apertado ativa alguma coisa.

Então diante desses quatro parâmetros, vamos começar a pensar.

A velocidade vai influenciar em quem? E ai pensou? Fácil essa, né? Bom, se a minha velocidade é 0, significa que eu estou parado, agora se é maior que zero, significa que eu vou andando.

Quando estaNoChao for falso, significa que o nosso personagem estará… pulando!

Quando eu disser atacou, significa que vamos chamar a animação atacando e quando eu disser morreu, chamaremos a animação morrendo. Ficou mais fácil de entender, né? Agora vamos organizar isso no Unity através das transições.

Caso o seu Unity assim como o meu fica meio ruim de enxergar todas as transições, basta clicar ali no olhinho, para expandir a visão:

38- Tutorial Personagem 1 -

39- Tutorial Personagem 1 -

Dai, você tenta deixar um pouco organizado as suas animações:

40- Tutorial Personagem 1 -

A primeira coisa que vamos fazer é criar uma animação saindo de parado para andando. Ou seja, clica com o botão direito em parado e vai na opção “Make Transition” e com a seta que surgir, a levaremos até andando:

41- Tutorial Personagem 1 -

42- Tutorial Personagem 1 -

Caso repare, vai ter surgido algo novo na aba Inspector ao clicar na setinha de transição que acabamos de criar. É lá onde teremos a condição de mudar de animação.

43- Tutorial Personagem 1 -

Clique então no “+” para adicionar a condição e selecione o parâmetro velocidade maior (greater) que 0.

44- Tutorial Personagem 1 -

Ou seja, quando a nossa velocidade for maior que zero e animação atual for parado, ele vai mudar para andando. Só mais um detalhe. Estão vendo o checkbox Has Exit Time? O desmarque.

46- Tutorial Personagem 1 -

Essa opção aqui diz que a transição só vai ocorrer quando a animação atual completar todos os sprites, sendo que nas animações continuas não é isso que a gente quer, ele pode parar no exato momento em que a condição ocorrer. Já nas animações como ataque, a gente só quer que ele mude de animação após completar todos os sprites.

Criamos a primeira transição, agora vamos fazer o caminho inverso, de andando para parado. Da mesma forma, clica com o botão direito em andando, escolha a opção “Make Transition”; Com a seta que surgir aponte para animação “parado”. Clica na seta e defina a condição velocidade menor (less) que 0.1

47- Tutorial Personagem 1 -

OBS: Se lembra de desmarcar a opção Has Exit Time, do contrário mesmo que você pare, seu personagem ainda vai fazer a animação correndo, até completar todos os sprites da animação.

Pronto! Agora vamos fazer de parado para pulando, sendo que aqui a condição será estaNoChao = false:

48- Tutorial Personagem 1 -

E mais uma vez desmarcamos a opção Has Exit Time. Vamos fazer exatamente o mesmo de andando para pulando:

49- Tutorial Personagem 1 -

Para fazer voltando, se a gente quisesse, poderíamos apenas fazer de pulando para parado, pois ao chegar na animação “parado” e a velocidade fosse maior que zero, então automaticamente ele irá para a animação andando. Mas para exercitar um pouco a mente, vamos criar as condições de “pulando” para “parado” e “andando”, de forma que cada uma terá duas condições:

Pulando para parado:

50- Tutorial Personagem 1 -

Condições: Estar no chão e sua velocidade ser menor que 0.1 (Ou seja, 0)

Pulando para andando:

51- Tutorial Personagem 1 -

Condições: Estar no chão e sua velocidade ser maior que zero.

Prontinho. Agora precisamos criar as transições de parado e andando em direção a atacando. A condição será apenas uma: apertei o botão (trigger) atacou:

52- Tutorial Personagem 1 -

Simples assim. Voltando iremos apenas por a animação de atacando para parado, pois quando estivermos atacando nosso personagem não poderá se mover. Então vamos criar uma transição de atacando para parado.

“Ta, ok, Carlos, mas e qual é a condição?” Bom, não vai existir nenhuma condição na realidade, porém vamos deixar a opção Has Exit Time marcado. Desta forma assim que ele entrar na animação atacando, não terá condição, então ele já pode seguir a próxima transição (voltar para parado), porém ele só fará isso após completar a animação, já que marcamos a opção Has Exit Time (Entendeu agora para que serve esse Has Exit Time?).

53- Tutorial Personagem 1 -

Para finalizar as nossas transições, vamos criar uma transição saindo de Any State (Ou seja, de qualquer animação) para morrendo, quando a condição for “morreu” (e morreu).

54- Tutorial Personagem 1 -

Pronto, com isso acabou nossa brincadeira com as animações, porém antes de irmos para os scripts, vamos trabalhar um pouco com a física do nosso personagem.

Caso a aba Animation ainda esteja aberta, desmarque o Record (Aquele símbolo de gravação, que fica ao lado do Play na aba Animation, para que as alterações realizadas não sejam na animação).

Clicando no Personagem1 lá na aba Hierarchy vamos adicionar o componente Rigidbody2D na aba Inspector:

55- Tutorial Personagem 1 -

Esse componente serve para que nosso personagem respeite a física do jogo como gravidade, saltos e essas coisas. Abrindo o Rigidbody 2D, lá em baixo na opção Constraints, vamos marca a opção Freeze Rotation Z.

56- Tutorial Personagem 1 -

Ela vai impedir que nosso personagem saia rodando por ai feito uma bola. Freeze Position X, impede que ele se mova na horizontal e o Freeze Position Y impede que ele se mova na vertical.

O próximo passo é adicionar um Circle Collider 2D no personagem:

57- Tutorial Personagem 1 -

Isso aqui fará a mágica da física: Dois corpos não podem ocupar o mesmo espaço. Ou seja, qualquer outro objeto com Collider não poderá ocupar o mesmo espaço que esse collider. Isso também permite podermos pisar no chão caso o chão também tenha algum collider. Outra coisa envolvendo os colliders é usar as funções de detecção, para saber se algo encostou-se a esse objeto.

Todavia se você marcar a opção Is Trigger, a lei da física de dois corpos não ocupam o mesmo espaço será ignorada:

58- Tutorial Personagem 1 -

Seria como se seu personagem fosse um fantasma e por isso pode passar pela parede. A ideia aqui é apenas manter a detecção de colisões, ou seja, mesmo você passando por dentro de um objeto, tem como você saber se seu personagem encostou ou não em outro. Porém não vamos marcar essa opção.

Mas olhando bem, esse circulo ficou muito grande, não é?

59- Tutorial Personagem 1 -

Então que tal a gente diminuir ele alterando a opção Radius.

60- Tutorial Personagem 1 -

Acho que 1, está bom, só posicionar agora em seus pés alterando 1:

61- Tutorial Personagem 1 -

“Carlos, por que não colocamos um quadrado ao invés de um circulo? Faz mais sentido não?”. Até que faz, mas se você tiver um degrau para subir, acha que seu personagem sai conseguir com um Collider quadrado? Se lembre de que seu personagem não sai girando ai (Marcamos a opção Freezing Rotation), então a menor diferença que existir no seu chão, fará seu personagem ficar preso, por isso usamos Circle.

“Ah , mas ficou uma parte enorme sem collider”. Verdade, então bora agora sim adicionar um Box Collider 2D na cabeça do personagem:

62- Tutorial Personagem 1 -

Prontinho. Agora está melhor não é mesmo?

OBS: Os meus campos estão em vermelho ali, porque o doente aqui esqueceu de tirar a opção Record da aba Animation, fazendo o collider existir apenas na animação. Então ignorem a cor. Fazia meses que não pegava no o Unity, estava desacostumado já.

O próximo passo para organizarmos as coisas por aqui antes de irmos para os scripts e montar um chão e um chão verificador. Para fazer o “chão verificador” clique com o botão direito sobre o Personagem1 na aba Hierarchy e escolha a opção create empty (Isso fará o novo objeto se filho de Personagem1). Ao objeto daremos o nome de chaoVerificador e vamos selecionar um ícone com alguma cor para ele:

63- Tutorial Personagem 1 -

64- Tutorial Personagem 1 -

Ele já está visível na aba Scene. Vamos puxa-lo um pouco para baixo do personagem:

65- Tutorial Personagem 1 -

A ideia aqui será ver se tem algum objeto entre nosso personagem e o chaoVerificador com a Layer Piso (Pode trocar o posição o arrastar o objeto na aba Scene).

O próximo passo é apenas criar um simples objeto que servirá de teste apenas. Esse objeto nós o chamaremos de “chao”:

66- Tutorial Personagem 1 -

Nele, vamos adicionar o componente Mesh Filter (Define a forma de um objeto):

67- Tutorial Personagem 1 -

Na opção Mesh, vamos escolher Quad:

68- Tutorial Personagem 1 -

Agora, vamos adicionar o componente Mesh Renderer (Define a textura de um objeto):

69- Tutorial Personagem 1 -

Já vai aparecer um quadrado no chão. Podem ficar tranquilos, que eu não estou explicando exatamente o que é cada uma dessas coisas, pois vamos ver melhor isso quando criamos o nosso cenário. Essa parte agora servirá apenas para testar o nosso script de movimento ;).

Esse quadrado rosa ai por enquanto será o nosso chão, então bora aumentar a sua escala em X (Altera na opção Scale na aba Inspector):

70- Tutorial Personagem 1 -

Em seguida, vamos adicionar um Box Collider 2D ao objeto chao:

71- Tutorial Personagem 1 -

Ele automaticamente já toma o tamanho do objeto. Por fim, vamos dizer a qual layer ele pertence. Então vamos clicar em Layer no Inspector e em seguida Add Layer:

72- Tutorial Personagem 1 -

Em User Layer 8 (Ou em qualquer outro que você puder digitar), criemos o “Piso”:

73- Tutorial Personagem 1 -

Então, voltamos a clicar no objeto chão na aba Hierarchy e na aba Inspector aplicamos o Layer Piso:

74- Tutorial Personagem 1 -

Perfeito! Agora vamos iniciar um script dentro da pasta jogador chamado Personagem1:

75- Tutorial Personagem 1 -

Abra o Script e a primeira coisa que faremos é dizer que ele não vai herdar de MonoBehavour, mas sim da classe abstrata Jogador, que criamos na aula passada:

76- Tutorial Personagem 1 -

Com isso irá aparecer uma mensagem de erro dizendo que o método abstrato atacar não foi implementado. Então clica na lampadazinha e escolhe Implement Abstract Class:

77- Tutorial Personagem 1 -

Podemos também remover o Start e o Update, pois eles já estão implementados na classe mãe:
Script: Personagem1.cs

using UnityEngine;
using System.Collections;
using System;

public class Personagem1 : Jogador {

    protected override void atacar()
    {
        throw new NotImplementedException();
    }
}

Bom, por hora já podemos salvar esse script e jogar lá no nosso Personagem1:

78- Tutorial Personagem 1 -

79- Tutorial Personagem 1 -

Aqui, iremos definir a velocidade que nosso personagem vai andar e a força do seu pulo. Também pegamos o Animator e o Chao Verificador.

O Animator será o do próprio objeto, então podemos simplesmente clicar no Personagem1 e arrastar ele para o Animator, que ele já vai pegar o Animator contido no objeto:

80- Tutorial Personagem 1 -

Fazemos o mesmo com o chaoVerificador e depois definimos a nossa velocidade (10) e a força do pulo (400):

82- Tutorial Personagem 1 -

Ao dar play o nosso personagem já começa com a animação do pulo, pois como não informamos para o Animator qual era o valor do parâmetro estaNoChao do animator, ele automaticamente trata como se fosse falso. Então bora informar esses valores para o animator, abrindo o script Jogador.

Lembra-se da nossa variável animator que não usamos na aula passada. Iremos usá-la agora. No Inspector falamos que o Animator usado no script Personagem1 é o do objeto Personagem1, correto? É ele, que tem todas aquelas animações e parâmetros. Agora no script vamos alterar os valores desses parâmetros do Animator.

O primeiro será a velocidade, então no método mover, logo após o comando de movimentar para esquerda ou direita, vamos passar para o nosso animator a informação da velocidade (Que é do tipo float, lembra?):

animator.SetFloat("velocidade", Mathf.Abs(Input.GetAxisRaw("Horizontal")));

83- Tutorial Personagem 1 -

Ao trabalhar com os parâmetros do nosso animador usaremos os métodos:

SetFloar -> Quando o parâmetro for float
SetBool -> Quando o parâmetro for Bool
SetInt -> Quando o parâmetro for inteiro
SetTrigger -> Quando o paramêtro for do tipo Trigger.

Onde o primeiro atributo do método será o nome que demos ao parâmetro. Ou seja, nesse caso, velocidade. O segundo será o valor que estamos atribuindo a esse parâmetro. Já vimos para que serve o método Input.GetAxisRaw(“Horizontal”), correto? Ele irá retornar 1 quando apertamos pro lado direito e -1 quando apertamos para o lado esquerdo. Então o que você acha que faz o Mathf.Abs()? Vai uma dica, o Abs é de absoluto. Se você não andou faltando as aulas de matemática, deve saber que o absoluto é o valor positivo de qualquer número. Desta forma, mesmo que a gente aperte para ele ir para a esquerda (-1), iremos dizer que a velocidade é 1. E se a velocidade for 1, significa que ela é maior que zero, desta forma irá ativar a condição da transição que fizemos mais cedo (parado -> andando)!

Bom, um já foi, agora vamos para o do pulo. Logo abaixo dessa linha que adicionamos, tinha uma variável estaNoChao do tipo booleana, correto? Então aqui é simples, vamos passar o valor dela para o parâmetro estaNoChao do animator:

animator.SetBool("estaNoChao", estaNoChao);

84- Tutorial Personagem 1 -

Simples assim. Antes de continuarmos, bora só adicionar os outros dois parâmetros. O morrendo, vai ocorrer quando o personagem sofrer dano, então será no método recebeDano da classe Jogador:

Script: Jogador.cs

    public void recebeDano(int dano) {
        status.sofrerDano(dano);

        if (status.estaMorto())
            animator.SetTrigger("morreu");
    }

Depois que o personagem sofrer um dano, vamos verificar se ele está morto. Se ele estiver. Apertamos o botão mágico (trigger) do parâmetro morreu. Como a animação morreu é chamada de qualquer animação (Any State) quando o trigger morreu, for selecionado, então a animação será chamada assim que o personagem morrer.

Já o trigger do ataque vai ser dentro do método ataque no script Personagem1. Lá, por enquanto vamos apenas pôr o trigger caso o jogador aperte um botão (Fire1 = ctrl da esquerda), ativando a animação:

Script: Personagem1.cs

using UnityEngine;
using System.Collections;
using System;

public class Personagem1 : Jogador {

    protected override void atacar() {
        if (Input.GetButtonDown("Fire1"))
            animator.SetTrigger("atacou");
    }
}

“Carlos, Carlos, funcionou!! Porém mesmo com a opção Has Exit Time, ainda há uma pequena demora na transição!”

Bom, neste caso, você pode voltar lá na aba Animator, clicar na transição que você acha que está demorando e ir na opção Settings que fica logo abaixo do “Has Exit Time”. Lá terá a opção Transition Duration. Diminua esta opção para 0 ou a velocidade que achar melhor:

85- Tutorial Personagem 1 -

Agora deve está uma beleza ;).

Aproveitando que estamos nessa tela do animator, basta clicar ali no Morreu, para ativar o trigger, enquanto o jogo estiver rodando e verá a animação dele morrendo:

86- Tutorial Personagem 1 -

Bom, para finalizar o tutorial de hoje, vamos trabalhar no script. Primeiro vamos criar uma variável do tipo booleana chamada atacando no script do jogador. Essa variável servirá para evitar que nosso personagem saia andando enquanto a animação do ataque estiver rodando:

87- Tutorial Personagem 1 -

Script: Jogador.cs

public bool atacando;               //Verifica se o jogador está atacando

Já no Update, podemos por uma condição, que se atacando for false então não pode mover e que se o personagem estiver pulando não pode atacar:

Script: Jogador.cs

    void Update() {
        if (atacando == false)
            mover();
        if (estaNoChao == true)
            atacar();
    }

Ou

Script: Jogador.cs

    void Update() {
        if (!atacando)
            mover();
        if (estaNoChao)
            atacar();
    }

As duas formas acima estão corretas. A atacando == false é mais fácil de visualizar para quem não tem tanta experiência, mas eu recomendo sempre usar a segunda forma (negação da informação, ou seja, se atacando for falso, então a condição é verdadeira) para exercitar o seu pensamento em lógica.

Agora vamos voltar ao Unity, lá na aquela opção dos Inputs que eu comentei aula passada, lembra?

88- Tutorial Personagem 1 -

Aqui, vou trocar as opções Fire1, Fire2 e Fire3 para Habilidade1, Habilidade2, Habilidade3:

89- Tutorial Personagem 1 -

E troquei os botões de ações (Positive Button) para 1, 2 e 3:

90- Tutorial Personagem 1 -

91- Tutorial Personagem 1 -

92- Tutorial Personagem 1 -

Os botões alternativos continuam sendo os do mouse.

Um pouco de explicações disso. O Name é o mesmo valor que chamamos no nosso Input.GetButton(“Nome”) ou Input.GetAxis(“Nome”). O Positive Button retorna o valor 1 quando o apertamos. Negative Button retorna -1. Os Alt ou botões alternativos servem para a mesma coisa dos botões normais, funciona como as setinhas e as teclas wasd para movimentação.Sensitivity é a velocidade com qual o valor sai do valor zero até o 1 ou -1, quando o usuário aperta o botão e o Gravity é o contrário, ou seja, a velocidade com qual o valor voltar ao zero quando o jogador deixa de apertar o botão.

Agora vou criar um novo botão que não existe trocando o campo Axes Size de 18 para 19:

93- Tutorial Personagem 1 -

OBS: Aperter Enter para confirmar

Foi duplicado o botão Cancel lá embaixo. Agora eu troco o nome dele para Ataque e coloco o botão Shift Esquerdo:

94- Tutorial Personagem 1 -

Pronto. Voltando ao Script Personagem1 vamos alterar o ataque:

Script: Personagem1.cs

    protected override void atacar() {
        if (!atacando) {
            if (Input.GetButtonDown("Ataque")) {
                animator.SetTrigger("atacou");
                atacando = true;
            }
            
        } else {
            atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");
        }
    }

O que exatamente estamos fazendo aqui? A primeira coisa, estamos verificando se o personagem já está ou não está atacando. Se ele não estiver atacando (if (!atacando)), então entrará na condição de poder atacar.

Ao clicar no botão de Ataque (Que é o shift da esquerda), iremos ativar o trigger atacou do animator e dizer que o personagem está atacando (atacando = true). Então no próximo frame, caso o seu personagem ainda esteja atacando ele irá entrar no else (O else é o senão, é onde entra caso da condição do if não ser aceita).

O método GetCurrentAnimatorStateInfo(0), irá pegar informações da atual animação que está rodando. E o método IsName(“nomeDaAnimacao”), retorna true se a animação atual for a que tu colocou o nome ali. Ou seja, se a animação atual já não for mais a atacando, então atacando receberá false, logo o seu personagem poderá voltar a atacar e a andar.

Salva o script e bota o unity ai para rodar e ver se esta tudo ok. Caso o seu personagem ainda esteja andando mesmo no ataque, recomendo a diminuir o tempo da transição, como fizemos agora a pouco com o pulo, isso deve funcionar ^^.

Bom, agora vamos criar um novo objeto na nossa aba Hierarchy e a chamaremos de AtaqueEspada:

95- Tutorial Personagem 1 -

Nele, iremos colocar um Box Collider 2D mais ou menos do tamanho do personagem (Será área do ataque da espada):

96- Tutorial Personagem 1 -

Agora, vamos marcar a opção Is Trigger, pois não queremos que o ataque empurre o personagem ou o inimigo, apenas que identifique que tocou em algo:

97- Tutorial Personagem 1 -

O próximo passo é criar um script para o ataque, então na pasta scripts/jogador vamos criar um script chamado Ataque:

98- Tutorial Personagem 1 -

Abrindo o script iremos criar o método OnTriggerEnter2D que será chamado sempre que o objeto tocar em algo. E caso esse objeto possua a tag inimiga, nosso ataque será destruído:

Script: Ataque.cs

    void OnTriggerEnter2D(Collider2D colisor) {
        if (colisor.gameObject.tag.Equals("Inimigo")) {
            Destroy(gameObject);
        }
    }

Como usamos lá a opção Is Trigger no nosso collider, nossos métodos serão do tipo OnTriggerAlgumaCoisa2D. Basicamente existem 3 tipos:

OnTriggerEnter2D – Funciona apenas no primeiro frame que o objeto tocar. Mas se o objeto sair e tocar novamente, vai ativar de novo;
OnTriggerStay2D – Ativo enquanto o objeto estiver dentro do campo do collider;
OnTriggerExit2D – Ativo apenas no primeiro frame que o objeto deixa de tocar.

A variável colisor ali, permitirá a gente pega algumas informações do objeto que colidiu ou da colisão. No nosso caso estamos verificando se o objeto possui a tag “Inimigo”. Caso tenha, depois nós iremos causar dano no inimigo e o ataque irá sumir.

Terminamos? Ainda não, falta criar um método que irá definir o tempo de vida do ataque, afinal o ataque não vai estar lá para sempre, né?

Script: Ataque.cs

    public void destroiObjeto(float tempo) {
        Destroy(gameObject, tempo);
    }

Ou seja, o nosso ataque irá sumir de acordo com o tempo que definirmos. Para finalizar esse script vamos definir o dano do nosso ataque. Então para isso, vamos criar uma variável do tipo int, que será o dano, com a visibilidade public. Assim nosso script será:

Script: Ataque.cs

using UnityEngine;
using System.Collections;

public class Ataque : MonoBehaviour {

    public int dano;  //Dano causado pelo ataque

    public void destroiObjeto(float tempo) {
        Destroy(gameObject, tempo);
    }

    void OnTriggerEnter2D(Collider2D colisor) {
        if (colisor.gameObject.tag.Equals("Inimigo")) {
            Destroy(gameObject);
        }
    }
}

Bom, agora voltando ao editor do Unity e vamos atribuir o script Ataque ao objeto AtaqueEspada:

99- Tutorial Personagem 1 -

Para finalizar com esse objeto, vamos criar uma pasta chamada prefabs e dentro desta pasta vamos criar outra chamada “jogador”:

100- Tutorial Personagem 1 -

O próximo passo é bem simples, basta pegar o AtaqueEspada da aba Hierarchy e arrasta para dentro da pasta prefabs/jogador:

101- Tutorial Personagem 1 -

Com isso criamos um prefab do AtaqueEspada, ou seja, sempre que o quisermos basta chamar ele no prefab, já podemos até excluir ele lá da aba Hierarchy:

102- Tutorial Personagem 1 -

Pronto, agora de volta ao nosso script Personagem1, vamos criar uma nova variável que do tipo Ataque:

Script: Personagem1.cs

public class Personagem1 : Jogador {

    public Ataque ataque;
...
}

Nós iremos agora ao clicar no botão de ataque criar o prefab AtaqueEspada.

“Oxe, mas o AtaqueEspada não é um GameObject? E por que estamos criando uma variável do tipo Ataque?”

É , isso que você pensou é verdade, mas o nosso script Ataque ele herda o MonoBehavour, lembra?

103- Tutorial Personagem 1 -

Então, não terá problema, pois ele já saberá quem é o GameObject que está atrelado a esse script e com isso já poderemos acessar os conteúdos direto do script sem precisar resgata-lo usando gameObject.GetComponent();, entendeu?

Então vamos criar um novo objeto AtaqueEspada utilizando o método Instantiate após o SetTrigger(“atacou”):

if (!atacando) {
    if (Input.GetButtonDown("Ataque")) {
        animator.SetTrigger("atacou");
        var objAtaque = Instantiate(ataque);
        atacando = true;
    }
}

Salve o script e volte ao Unity. Clique no Personagem1 na aba Hierarchy e depois na Aba Inspector diga que o nosso prefab AtaqueEspada será o ataque:

104- Tutorial Personagem 1 -

E dê play para ver como está o seu jogo:

105- Tutorial Personagem 1 -

Toda vez que você aperta o shift para atacar, ele cria os objetos de AtaqueEspada, porém não os destrói e nem o posiciona no local correto. Isso ocorre porque a gente não chegou a mexer nesses pontos, então bora lá voltando ao script.

A primeira coisa que vamos fazer com o objAtaque que acabou de instanciar é definir o tempo de destruição dele:

Script: Personagem1.cs

    protected override void atacar() {
        if (!atacando) {
            if (Input.GetButtonDown("Ataque")) {
                animator.SetTrigger("atacou");
                var objAtaque = Instantiate(ataque);
                objAtaque.destroiObjeto(animator.GetCurrentAnimatorStateInfo(0).length);
                atacando = true;
            }
            
        } else {
            atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");
        }
    }

O que adicionamos foi a seguinte linha:

objAtaque.destroiObjeto(animator.GetCurrentAnimatorStateInfo(0).length);

O destroiObjeto já sabemos o que faz, ele diz que o objeto de ataque vai ser destruído dentro de um determinado tempo. O animator.GetCurrentAnimatorStateInfo(0) nós sabemos que ele pega informações relacionadas a animação atual. O lenght nada mais é do que a duração dessa animação. O que significa diz que nós iremos destruir o objeto AtaqueEspada dentro do tempo da animação.

Execute o seu jogo e veja o resultado

106- Tutorial Personagem 1 -

O objeto já está sendo destruído. Então o próximo passo é posiciona-lo a frente do personagem. Então vamos voltar lá no nosso script, onde vamos verificar se o nosso personagem está virado para o lado direito ou esquerdo. Caso esteja para direita, vamos adicionar o AtaqueEspada com a posição atual do seu personagem + duas posições para a direita (x = 2). Caso ele esteja para a esquerda, vamos adicionar com a posição atual do personagem + duas posições a esquerda (x = -2):

Script: Personagem1.cs

protected override void atacar() {
        if (!atacando) {
            if (Input.GetButtonDown("Ataque")) {
                animator.SetTrigger("atacou");
                var objAtaque = Instantiate(ataque);
                objAtaque.destroiObjeto(animator.GetCurrentAnimatorStateInfo(0).length);

                if (direita)
                    objAtaque.transform.position = transform.position + (Vector3.right * 2);
                else
                    objAtaque.transform.position = transform.position - (Vector3.right * 2);

                atacando = true;
            }
            
        } else {
            atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");
        }
    }

Explicando melhor o que acabamos de fazer:

SE (Personagem estiver virado para direita)

A posição do objeto AtaqueEspada vai receber a posição do personagem + dois passos a direita

SENÃO (Personagem não estiver virado para direita)

A posição do objeto AtaqueEspada vai receber a posição do personagem + dois passos a esquerda.

Ou seja se nosso personagem estiver na posição X = 3, Y = 1, Z = 0, nosso ataque na direita será:
(X = 3, Y = 1, Z = 1) + ((X = 1, Y = 0, Z = 0) * 2)
(X = 3, Y = 1, Z = 1) + (X = 2, Y = 0, Z = 0)
(X = 5, Y = 1, Z = 1)

E se ele tiver virado para a esquerda, será:
(X = 3, Y = 1, Z = 1) – ((X = 1, Y = 0, Z = 0) * 2)
(X = 3, Y = 1, Z = 1) – (X = 2, Y = 0, Z = 0)
(X = 1, Y = 1, Z = 1)

Vamos ver isso no Unity como ficou?

Virado para esquerda:

111- Tutorial Personagem 1 -

Virado para direita:

112- Tutorial Personagem 1 -

Finalizado? Quase, basta definirmos o dano. Então mais uma vez vamos voltar lá ao script no ataque e informar o dano do ataque adicionando a linha objAtaque.dano = status.getAtaque();:

Script: Personagem1.cs

protected override void atacar() {
        if (!atacando) {
            if (Input.GetButtonDown("Ataque")) {
                animator.SetTrigger("atacou");
                var objAtaque = Instantiate(ataque);
                objAtaque.destroiObjeto(animator.GetCurrentAnimatorStateInfo(0).length);

                if (direita)
                    objAtaque.transform.position = transform.position + (Vector3.right * 2);
                else
                    objAtaque.transform.position = transform.position - (Vector3.right * 2);

                objAtaque.dano = status.getAtaque();

                atacando = true;
            }
            
        } else {
            atacando = animator.GetCurrentAnimatorStateInfo(0).IsName("atacando");
        }
    }

Bom, se você for executar agora, ele vai dizer que o objeto status é nulo e de fato é, pois não o iniciamos, nem definimos a vida ou magia do personagem. Então bora lá! Iremos usar agora um método do Unity que é usado para setar informações próprias, o método Awake, que é chamado toda vez que o script é criado e antes do método Start (Ou seja, no Awake podemos colocar informações nossas e no Start colocamos informações de outros objetos, por exemplo):

Script: Personagem1.cs

    void Awake() {
        status = new Status(20, 6, 10);
    }

Caso não lembrem nós criamos um construtor do Status de forma que fosse (HP, MP e Ataque), então nosso personagem terá 20 de vida, 6 de ponto de magia e 10 de ataque.

Com isso sim finalizamos esse tutorial.

Esse ficou maior que o outro, mas foi apenas por conta das imagens. Na pratica é bem menor, mais simples e mais divertido que o ultimo tutorial não é mesmo? No próximo post vamos criar as 3 habilidades do nosso ninja.

Índice Tutorial Intermediário

Download do Projeto

Download do Jogo

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

70 comments

  1. Bruno Souza disse:

    Muito bom o seu tutorial. Estou começando a programar games indie agora com uns amigos, e sua metodologia é a melhor e mais completa que encontrei na internet. Me empolguei para aprofundar nisso depois que vi seu tutorial. Parabéns, continue assim.

    • Valeu mesmo Bruno. Fiquei com receio desse tutorial ter pego mais pesado, já que estou puxando mais pesado de vocês (Afinal, se vocês desenvolverem bem a ideia de programação no Unity, vocês constroem qualquer coisa, até mesmo o que eu não ensinei).

  2. Bruno Souza disse:

    Seria recomendável mesmo a pessoa ter um pouco de noção antes. Eu fiz uns tutoriais básicos que encontrei, mas assim que vi o seu eu ja comecei a me familiarizar. É pesado, mas nada que um pouco de atenção a pessoa não aprenda. Espero aprender muito com você nesse tutorial.

  3. rafael disse:

    brother otima iniciativa sua, acompanho desde as primeiras lições, agora uma duvida, eu fiz de outra maneira a colisão, eu fiz com que a caixa de colisão aparecesse na animação, entendeu?

  4. Hugo E.R. Ferreira disse:

    Olá Carlos, tenho uma dúvida a respeito da programação. Na classe Status você corta a associação dessa classe com o MonoBehaviour isso quer dizer que nessa classe não poderia utilizar por exemplo o OnTriggerEnter2D?

    • Perfeitamente Hugo.

      Todos os métodos especiais como: Update, Start, OnTriggerEnter2D… e variáveis como: transform, gameObject, tag… não existem ao remover o MonoBehaviour.

      É como uma classe totalmente nova, por tanto vázia.

  5. Hugo E.R. Ferreira disse:

    Agradeço pela atenção Carlos, mas fiquei com uma coisa confusa na cabeça, ainda sobre programação. Você usou o método Update do MonoBehaviour no script Jogador, se você utilizasse novamente o método Update no script Personagem iria dar erro?

    O motivo da dúvida é que eu queria acrescentar ações únicas para cada personagem, mas não sei se posso reutilizar os métodos na classe filha.

    • Pode sim usar Hugo. Você irá sobrescrever sobre o código da classe mãe. Mas em C# para fazer isso, na classe mãe você informa que o método é virtual (pode ser sobrescrito) e na classe filha você usa override para sobrescrever o método ficando assim:

      Mãe:
      protected virtual void Update() { … }

      Filha
      protected override void Update() { … }

      Em tutoriais mais para frente você vai ver isso ^^

  6. Vinícius disse:

    Cara, eu tava seguindo o tutorial e estava tudo dando certo, mas quando chegou na parte q vc falou: ” Aproveitando que estamos nessa tela do animator, basta clicar ali no Morreu, para ativar o trigger, enquanto o jogo estiver rodando e verá a animação dele morrendo:”, eu fui fazer isso pra ver a animação dele morrendo aqui, mas eu vi um erro q n consegui resolver sozinho, assim q eu dou play: o personagem automaticamente entra na animação de ”pular” infinito e trava no ar, tipo ele fica ”voando” com as pernas abertas (q faz parte da animação de pulo) eu até posso controlar ele no ar e fazer ele voar pra frente e pra trás com as pernas de pulo ‘-‘. Se poder me ajudar, agradeço

    Ótimo tutorial e muito obrigo por compartilhas seus compartilhamentos com a galera! 😉

    • É porque não deve ter sido informado ainda os valores no Animator via script ^^

      Ou seja para ele o Default é que o chão seja false, logo estará sempre voando.

      Caso já tenha definido os dados no animator, é só verificar se o chaoVerificador está mais abaixo do personagem, possibilitando o chão entre o personagem e o objeto chaoVerificador.

  7. Reginaldo disse:

    tem como usar o propio personagem(e colocar o script de ataque no script do player) para a animação do ataque sem precisar criar um objeto só paraa o ataque?

    • Se desejar sim. Não existe regras para fazer jogo. Cada um tem sua proposta ^^

      O risco com essa animação é você atacar de costas, mas se a sua animação não importar o lado, pode sim usar no próprio objeto.

  8. Reginaldo disse:

    eu fiz uns trambiques nos scripts usando o tutorial basico mas n deu certo a parte de destruir o inimigo vc podde ver oq ta errado pf
    using UnityEngine;
    using System.Collections;

    public class Player : MonoBehaviour {
    public float velocidade;
    public float forcaPulo;
    private bool estaNoChao;
    public Transform chaoVerificador;
    public Transform spritePlayer;
    private Animator animator;
    public float duracaoatacou;
    private float contagematacou;
    public GameObject vida;
    public int maxVida;
    private int vidaAtual;
    //Tudo que ocorre quando o personagem e criado
    void Start () {
    animator = spritePlayer.GetComponent ();

    //Vida
    vidaAtual = maxVida;
    vida.GetComponent().color = new Vector4(0.25f, 0.5f, 0.25f, 1f);
    vida.GetComponent().text = “HP: ” + vidaAtual + “/” + maxVida;
    }
    //perde vida
    public void PerdeVida(int dano) {
    vidaAtual -= dano;

    if (vidaAtual <= 0) {
    Application.LoadLevel(Application.loadedLevel);
    }

    if ((vidaAtual * 100 / maxVida) < 30) {
    vida.GetComponent().color = Color.red;
    }

    vida.GetComponent().text = “HP: ” + vidaAtual + “/” + maxVida;
    }
    //ganhavida
    public void RecuperaVida(int recupera) {
    vidaAtual += recupera;

    if (vidaAtual > maxVida) {
    vidaAtual = maxVida;
    }

    if ((vidaAtual * 100 / maxVida) >= 30) {
    vida.GetComponent().color = new Vector4(0.25f, 0.5f, 0.25f, 1f);
    }

    vida.GetComponent().text = “HP: ” + vidaAtual + “/” + maxVida;
    }
    //Tudo que ocorre enquanto o personagem existe
    void Update () {
    Movimentacao();
    }

    //Responsavel pela movimentacao do personagem
    void Movimentacao ()
    {

    //Seta no paramentro movimento, um valor 0 ou maior que 0. Ira ativar a condicao para mudar de animacao
    animator.SetFloat (“movimento”, Mathf.Abs (Input.GetAxisRaw (“Horizontal”)));

    //Anda para a direita
    if (Input.GetAxisRaw (“Horizontal”) > 0) {
    transform.Translate (Vector2.right * velocidade * Time.deltaTime);
    transform.eulerAngles = new Vector2 (0, 0);
    }

    //Anda para a esquerda
    if (Input.GetAxisRaw (“Horizontal”) < 0) {
    transform.Translate (Vector2.right * velocidade * Time.deltaTime);
    transform.eulerAngles = new Vector2 (0, 180);
    }

    //Verifica se esta no chao
    estaNoChao = Physics2D.Linecast (transform.position, chaoVerificador.position, 1 << LayerMask.NameToLayer ("Piso"));
    animator.SetBool ("chao", estaNoChao);
    //ataque
    if (Input.GetButtonDown ("Fire1")) {
    animator.SetTrigger ("atacou");
    }
    //Responsavel pelo pulo
    if (Input.GetButtonDown ("Jump") && estaNoChao) {
    if (Input.GetButtonDown ("Jump") && estaNoChao) {
    GetComponent ().AddForce (transform.up * forcaPulo);
    }
    }
    }
    }

    • Você apenas criou a parte da animação:

      if (Input.GetButtonDown ("Fire1")) {
      animator.SetTrigger ("atacou");
      }

      Não criou nada relacionado ao dano o inimigo.

      1 – No caso nessa condição ai, você ia ter que ativar uma condição “atacando = true”
      2 – um time para indicar o tempo da duração do ataque para depois transforma o “atacando = false”;
      3 – Um OnTriggerStay2D, para causar o ano, caso tenha encostado em um objeto com a tag inimigo e atacando seja igual a true e não tenha ainda acertado o inimigo atual (Caso destrua o inimigo sem levar em consideração o dano, basta ignorar essa parte de verificar se já acertou o inimigo atual).
      Um

  9. Reginaldo disse:

    vlw mas tipo eu fiz esse codigo usando o basico e ta rodando +/- pode buga bo futuro?
    void Ataque ()
    {
    if (Input.GetButtonDown (“Fire1”)) {
    animator.SetTrigger (“atacou”);
    }
    if (Input.GetButton (“Fire1”)) {
    ataqueEspecial.SetActive (true);
    contagemAtaque = 0f;
    }

    if (Input.GetButtonDown (“Fire2”)) {
    ataqueEspecial.SetActive (false);
    }
    if (Input.GetButtonDown (“Fire3”)) {
    animator.SetTrigger (“espada”);
    }
    if (Input.GetButton (“Fire3”)) {
    ataqueEspada.SetActive (true);
    contagemAtaque = 0f;
    }

    if (Input.GetButtonDown (“Fire2”)) {
    ataqueEspecial.SetActive (false);
    ataqueEspada.SetActive (false);
    }
    }
    }

    • Na realidade está bem confuso. Por quê?

      1 – Como você não está seguindo o tutorial eu não exatamente o que cada coisa faz. Mas talvez eu imagine que o Fire1, Fire2 e Fire3, represente o habilidade1, habilidade2, habilidade3, mas não tenho certeza já que o Fire2 parece não causa um ataque O.o
      2 – Você repete o if (Input.GetButtonDown (“Fire1”)) e o if (Input.GetButton (“Fire3”)), mas não sei o motivo, já que fazem a mesma coisa.
      3 – No if (Input.GetButton (“Fire2”)), você desativa o ataqueEspecial, pelo jeito, mas então porque contagemAtaque está ali? Está meio confuso, uma vez que não sei a ideia de cada coisa existir.
      Eu enxugaria esse código deixando assim:

      void Ataque () {
      if (Input.GetButtonDown (“Fire1”)) {
      animator.SetTrigger (“atacou”);
      ataqueEspecial.SetActive (true);
      contagemAtaque = 0f;
      }

      if (Input.GetButtonDown (“Fire2”)) {
      ataqueEspecial.SetActive (false);
      ataqueEspada.SetActive (false);
      }

      if (Input.GetButtonDown (“Fire3”)) {
      animator.SetTrigger (“espada”);
      ataqueEspada.SetActive (true);
      contagemAtaque = 0f;
      }
      }

  10. Reginaldo disse:

    esqueci d tira a contagem xD tiipo o fire1 e fire 3 sao golpes e animaçoes diferentes e como a colisao dos ataques ficava msm depois d acaba o atk eu coloquei pra fecha no fire2

  11. Reginaldo disse:

    eu tentei void Ataque () {
    if (Input.GetButtonDown (“Fire1”)) {
    animator.SetTrigger (“atacou”);
    ataqueEspecial.SetActive (true);
    contagemAtaque = 0f;
    } //mas n funciono

  12. Reginaldo disse:

    tipo antes era o dano +arrumei agr o problema é q n consigo fechar a colisao sem precisar usar o fire 2(se n uso o fire 2 ele continua matando os monstros sem atk)

  13. Reginaldo disse:

    fmz

  14. Álvaro disse:

    Olá! Bom dia ou tarde ou noite rsrs. Não funcionou como devia a animação de ataque não entendi o pq, mas tbm não apresentou erro no console. Acabei ajeitando do meu jeito, espero que isso não atrapalhe na continuidade dos tutoriais. O código teve uma leve alteração;

    using UnityEngine;
    using System.Collections;

    public class Personagem1 : Jogador {

    public Ataque ataque;
    public float tempoAnin; // tempo de duração da animação
    public float tempoCorrente; // tempo corrente

    protected override void atacar()
    {
    if (!emAtaque)
    {
    if (Input.GetButtonDown (“Ataque”))
    {
    var objAtaque = Instantiate (ataque);
    animator.SetTrigger (“atacou”);
    tempoAnin = animator.GetCurrentAnimatorStateInfo (0).length;
    objAtaque.destroiObjeto ((int)animator.GetCurrentAnimatorStateInfo (0).length);

    emAtaque = true;
    tempoCorrente = 0;
    }
    }

    if (emAtaque)
    {
    tempoCorrente += Time.deltaTime;
    if (tempoAnin <= tempoCorrente) {
    tempoCorrente = 0;
    emAtaque = false;
    }
    }

    }
    }

    • Opa Álvaro, desculpe a demora.

      O que exatamente não funcionou na animação? Ela iniciar ou ela parar? O.o

      Acredito que o erro não deva estar no código e sim nas condições do Animator.

  15. Jhonatan disse:

    O meu jogo não esta desligando a animação dele atacando depois que eu aperto o botão de atacar

    private void atacar()
    {
    if (atacando == false)
    {
    if (Input.GetButtonDown(“bater”)) aqui em vez de ataque eu coloquei bater mesmo
    {
    animator.SetTrigger(“atacou”);
    atacando = true;
    }

    }
    else
    {
    atacando = animator.GetCurrentAnimatorStateInfo(0).IsName(“atacando”);
    }

    }

    • E ai Jhonatan, tudo joia?

      Pelo que você falou, para mim o erro deve estar no Animator. Na condição da animação atacando para parado. Verifica lá se você adicionou a transição e se a caixinha Has Exit Time está marcada, para ele sair da animação após completa-la 😉

  16. Olá, estava seguindo o tutorial até certa parte e fui checar no play colocando um número de velocidade e Força pula para testar, e o cenário está caindo e quando eu aperto o espaço o cenário começa a ir pra cima. O que pode ser ?

  17. Julio disse:

    Chequei o cenário e ele não possui rigybody2d

  18. Julio disse:

    O Cenário quando o personagem se move para a esquerda ou para a direita se move também.

  19. Julio disse:

    Arrumei o erro eu havia colocado o chao dentro do Personagem1 por isso o personagem estava caindo

  20. Agora está dando outro erro, parameter “atacou” does not exist.

    • Julio, verifica se dentro do Animator que controla essa animação, tem um parametro chamado “atacou”. Não pode ser “Atacou” nem “ATACOU”, tem que ser “atacou”, igualzinho. Se trocar em um, tem que trocar em outro.

  21. Alexandre Izelli disse:

    Olá Carlos!
    Muito bom o seu tutorial, o texto esta muito bem elaborado, muito fácil de compreender.
    Gostaria apenas de deixar uma observação:
    Eu tive problemas com a execução da animação, onde após o termino da execução de ataque, o personagem ficava imóvel e não respondia aos comando, como se estivesse travado. Para quem estiver com o mesmo problema segue a solução (pelo menos funcionou para mim).
    Eu estava usando o código abaixo no método Update() da classe Jogador:

    if(atacando == false)
    mover();

    if(atacando == true)
    atacar();

    A solução foi alterar o código para esse:

    if(!atacando)
    mover();

    if(estaNoChao)
    atacar();

    • Opa Alexandre, valeu mesmo. ^^

      Quanto aos if, não tem problema em usar if(atacando == true) ou simplesmente if(atacando), o mesmo vale para o negativo if(atacando == false) e if(!atacando).

      O problema que rolou ali foi que em um if é atacando e no outro é estaNoChao e na primeira situação você usou atacando para os dois casos.

  22. Wanderson disse:

    Carlos estou com um problema,
    quando eu aperto meu botão de atacar meu personagem para e nao se meche nem roda nenhuma outra animação
    fiz o que o Alexandre disse ^^ meu personagem se moveu mas nao roudou nenhuma outra animaçao, isso é algum bug? ou errei alguma coisa no codigo ou na parte de animaçao?

    • Opa Wanderson. O problema está nas transições do animator provavelmente. Clica lá no seu personagem e volta na aba Animator.

      Verifica lá se colocou a transição do atacando para o está normal (parado) 😉

  23. Wanderson disse:

    quando dou play, aparece alguns avisos (a quele amarelinho no console)
    Trinsition in the state ‘atacando’ doesn’t have an Exit Time or any condition ,transition will be ignored

    • Essa mensagem ocorre quando lá no animator, você cria uma transição, mas não coloca nenhuma condição para ele ocorrer.

      Então é só ir na aba Animator e verificar a condição que sai de parado ou andando para atacando está com todos os dados preenchidos (Condição, trigger “atacou”)

  24. Wanderson disse:

    Consegui!!
    obrigado Carlos, obrigado por ter me ajudado e por ter colocado os tutoriais
    bom trabalho.Falta de atençao minha :v e olha que eu tinha conferido tudo um monte de fez .-.

  25. Boa noite.
    Voltei agora com outro erro KK
    Primeiramente gostaria de saber o que é o ” throw new NotImplementedException(); ”
    O erro que aparece quando eu dou play (ainda não terminei esse tutorial, estou tentando apenas testar se o personagem anda, acabei de criar o script) é a seguinte mensagem:
    NotImplementedException: The request feature is no implemented.
    Personagem1.atacar () (at Assets/Scripts/Jogador/Personagem1.cs:9)

    Acha que pode ser algo que eu possa ter errado no script jogador? .-.

    • Pow, só vi hoje teu comentário, estou bem né? >.< Então, primeiro temos que entender o que é Exception. Exception é uma chamada de erro que o desenvolvedor cria. De uma forma leiga, digamos que seja um erro customizável. Com isso nós podemos fazer várias coisas como tratar um erro especifico ou apenas impedir que o sistema seja executado se aconteceu algo. throw new NotImplementedException() que dizer que um determinado método não foi implementado, está vazio e deveria ser implementado. Ou seja, é uma espécie de lembre para o desenvolvedor, um erro que sempre vai acontecer enquanto ele não adicionar conteúdos a um determinado método que deveria implementar um método de uma interface. Pra que não aconteça o erro, basta tirar essa linha do seu método, mas se lembre de adicionar alguma funcionalidade a ela, do contrário não faria sentido ela existir 😉

  26. matheus disse:

    estou com o msm problema e n consigo arrumar,se vc conseguiu me explica como pls

  27. Boa noite, to com um problema aqui, toda vez que meu personagem toca o chão ele fica entrando na animação de pulo, mas faz só alguns frames da animação, e quando começo a mover o personagem ele vira de cabeça pra baixo e continua tentando entrar na animação de pulo, já revisei o código um milhão de vezes, e também revisei o Animator, mas não achei nenhuma solução. Poderia me ajudar ?

    • Esse problema de ficar pulando, é um erro clássico aqui já. Varias pessoas cometem. Neste caso verifica os seguintes pontos:

      1 – Checa se o chaoVerificador (Objeto filho do personagem) está com uma distância relativamente boa entre o personagem, possibilitando que exista um chao entre eles.

      2 – Checa se o seu objeto responsável pelo chão realmente está com a Layer Piso

      3 – Checa se a variavel booleano estaNoChao está ficando como false mesmo o persoagem estando no chão

      4 – Checa se o valor desta variavel estaNoChao está sendo passado para o Animator

      5 – Checa se as configurações de transição de animações estão certinha ^^

  28. Na verdade o problema de virar de cabeça pra baixo está no movimento, quando ando pra direita ele vira de cabeça pra baixo, esquerda ele volta ao normal

    • Huuuuum. Acredito que esse seu problema está no método inverter. É como você estivesse trocando a escala de Y ao invés da escala de X.

      Por isso que para um lado ele fica de cabeça para baixo e para o outro lado ele fica normal, quando seria para um lado ele está para esquerda e outro para direita.

      void inverter() {
      float x = transform.localScale.x;
      x *= -1;
      transform.localScale = new Vector3(x, transform.localScale.y, transform.localScale.z);
      }

  29. Opa, resolvi aqui, os dois problemas, a condição pra transição de “Parado” para “Pulando” estava como true, e o problema dele inverter era porque meu código estava assim
    transform.localScale = new Vector3(x, transform.localScale.x, transform.localScale.z);
    Estava passando a 2 vezes o parâmetro do eixo X, e um deles estava onde deveria estar o eixo Y, kkkk, deve ter sido o sono.
    Valew man, muito obrigado. ^^

  30. wellington disse:

    pra que fazer isso :

    if(atacando == false)
    mover();

    if(atacando == true)
    atacar();

    se eu posso fazer isso td pelo próprio animator, tem algum motivo ?

    • Opa Wellington, tem sim.

      No animator você apenas irá definir comportamentos relacionado a animação, já nos métodos atacar() e mover(), você vai trabalhar no comportamento do objeto em sim, como movimentá-lo pelo cenário ou causar dano a um inimigo.

      Não fica apenas na animação ^^

  31. Ae cara, firmeza? Você poderia me ajudar num problema aqui?
    Então, fiz todo tutorial da maneira que foi ensinada, porém tô com problema na hora de apertar o botão de ataque. Eu aperto o shift esquerdo e o personagem faz nenhuma ação. Já coloquei um Debug.Log no método ‘atacar’ e mesmo assim não retorna uma mensagem. Já verifiquei o animator e o código e eles estão iguais aos que você postou, já verifiquei o nome do botão na aba Input e o ‘positive button’ e eles também estão iguais! Me ajuda ai, por favor.
    Além do mais, ótimo tutorial.

    Vou deixar o link aqui do projeto para download, caso você queira dar uma olhada.
    https://mega.nz/#!hUBRzaRL!ByXYRMbEUt3_FBLrxASEFLWzV7Kn3zGDaA9zAx52bgE

    • Opa cara! O ataque na realidade não está rolando porque o método ataque() do Personagem1 não é chamado no método Update() de Jogador.

      Aquela parte:
      void Update() {
      if (!atacando)
      mover();
      if (estaNoChao)
      atacar();
      }

  32. Boa Noite ou Bom Dia Carlos,

    Te mandei um e-mail infelizmente sem titulo,
    mas estou utilizando a versão do Unity 5.4.1f1 (64-bit)
    e estou utilizando seus códigos e seguindo seu tutorial, mas o boneco não se move para a esquerda só para a direita nas teclas A.D e setas , baixei o seu projeto e deu no mesmo.
    O que pode ser?

    • Opa Cleberson.

      A partir da versão 5.4 (Lançada agora no final de Julho), ao mudar a escala do personagem para negativa, funciona igual a mudar a rotação.

      Então aonde tinha o “-Vector3.right” para andar para a esquerda, basta por o “Vector3.right” (Sem o valor negativo)

  33. Caique Diniz disse:

    Olá meu personagem não anda e nem pula, os sprites não funcionam, o que faço?

  34. Matheus Rodrigues disse:

    Fala, professor! Meu personagem não tá andando :[

  35. Daniel H.S. disse:

    Estou com pequeno bug no ataque do personagem, devido a imagem do personagem ser meio pequena, o ataque mesmo colocando
    –> objAtaque.transform.position = transform.position + (Vector3.right * 1(0 fica em cima dele)) <–
    o objeto do ataque vai parar uns 3x a largura dele pra frente, se eu colocar o 2 ele para do outro lado do mapa .-. obs: coloquei uma imagem pra mostrar onde tava indo.
    Tem como mutiplicar por um double ali no codigo ? ou não tem como tratar essas coisas usando o vector3 dessa maneira do tutorial ?

  36. Daniel H.S. disse:

    Ja arrumei e o erro foi retardado .-.
    Espero que não encontre erros assim na vida de programador que me espera :3 hehe

  37. Oomaschi disse:

    fala cara beleza, to com uma duvida aqui,

    tem uma parte onde add o script Personagem1 correto?

    essa aqui:
    “Bom, por hora já podemos salvar esse script e jogar lá no nosso Personagem1:”

    mas pra mim não aparece aquelas caixinhas com as opões animator e tal da segunda imagem abaixo disso. tá assim.
    Essa é a sua
    http://jogosindie.com/02-tutorial-intermediario-criando-personagem-parte-1/79-tutorial-personagem-1/

    Essa é a minha
    https://uploaddeimagens.com.br/imagens/captura_de_tela_2017-01-12_06-34-23-png

    e outra, cara como eu faço pra ajustar o personagem na tela scene igual a tela game. pq todas as propiedades dele estão igual ao tutorial, só essa aba que ta esquisita e isso atrapalha quando eu vou posicionar algum collider.

    • Se ela não aparece, pode estar acontecendo uma das duas coisas:

      1 – O script apresenta algum erro de sintaxe (Faltando ponto e virgula, um if errado, faltando alguma chave ou alguma coisa assim. Não é erra na lógica, mas sim no código mesmo)

      2 – Os campos não estão como publico (public)

  38. Oomaschi disse:

    Cara, eu fiz o seguinte, as 5 da manhã eu fiquei puto com os erros que tava dando e deletei o jogo, não quis pegar os scripts que tu põe no fim de cada parte, achei que não ia adiantar nada, só copiar e não praticar. daí eu to refazendo o projeto todo parte por parte bem devegar para fixar na minha mente, e olha que eu cheguei até a parte 2, quase parte 3.teve um pequeno problema até pq eu não fiz o tutorial básico pq minha versão do unity não é compativel fiquei meio defasado de conhecimentos basico. mas agora vai.

    espero terminar ele antes de sair o proximo tutorial.

    Grande abraço.

  39. Breno disse:

    ola Carlos

    em um projeto 2D tenho um inimigo que tem dois componentes Colliders, um BoxCollider2D e um PoligonCollider2D.
    um projetil vai acertar e colidir com os dois Colliders mas vai arrancar ponto de dano do inimigo só quando acertar o BoxCollider2D

    como é o script para verificar somente se o BoxCollider foi acertado?

  40. Oi Carlos, meu personagem continua se movendo quando esta atacando e nao sei oq esta errado
    (na classe do personagem)
    protected override void atacar()
    {
    if (!atacando)
    {
    if (Input.GetButtonDown(“Ataque”))
    {
    atacando = true;
    animator.SetTrigger(“ataque”);
    var objAtaque = Instantiate(ataque);
    objAtaque.destroiObjeto(animator.GetCurrentAnimatorStateInfo(0).length);

    if (direita)
    objAtaque.transform.position = transform.position + (Vector3.right * 2);
    else
    objAtaque.transform.position = transform.position – (Vector3.right * 2);
    }

    }
    else
    {
    atacando = animator.GetCurrentAnimatorStateInfo(0).IsName(“atacando”);
    }
    }
    (na classe do jogador)
    void Update()
    { if (atacando == false)
    Movimentacao();
    if (estaNoChao == true)
    atacar();
    }

  41. Edmar, a principio o script está ok, como estão as animações? Você chegou a fazer a transição de “atacando” para “parado”?

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!