Menu

01 – Tutorial Intermediário – Criando personagem principal

E aê meus queridos, tudo joia? Faz bastante tempo desde que pegamos no Unity, né não? Bom, mas hoje nesse primeiro tutorial vou botar pesado em vocês para irem se aquecendo para os próximos (Mentira, podem ficar tranquilo, mas…  é verdade que hoje será a parte mais puxada para vocês. Se vocês já soubessem tudo e fossem fazer o que teremos hoje no tutorial, vocês terminariam em 10 minutos, maaaaas como eu preciso explicar tudo bonitinho e detalhado, esse post será enoooorme e por isso vocês podem demorar talvez até 1h lendo e fazendo).

Bom, antes de começar vamos bater aquele papo que sempre rola em aulas inicias, onde o professor se apresentar e cada aluno também (Vocês não precisam, é lógico… a menos que queiram O.o). Aos que não me conhecem eu sou Carlos Lessa, também conhecido na internet como Carlos W. Gama (Se vocês virem alguém com esse nick em algum jogo, de certeza sou eu). Sou formado em análise de sistemas e trabalhei por anos com desenvolvimento de sites e sistemas web, onde encontrei a uma das minhas maiores paixões, a programação. Recentemente entrei no mestrado, o que me ocupou certo tempo (Por isso a demora para sair esse tutorial). Depois, assim como vocês, fui-me aventura um pouco com desenvolvimento de jogos e não achei muito material legal em português sobre criação de jogos (Em Unity, principalmente), foi então que eu pensei: “por que não?”. Eu já tinha começado o site Jogos Indie onde pretendia falar de jogos indie, então porque não abrir uma categoria de tutoriais de desenvolvimento de jogos? Foi assim que surgiu a categoria mais agitada do Jogos Indie, a de Tutorial de Unity 2D. A você pergunta: “Carlos você já criou algum jogo? Por que eu deveria ver seu tutorial?”. Bom na real eu nunca criei um jogo que eu publicasse abertamente e comercialmente, apenas os meus tutoriais, porém sempre tive vontade de abrir uma empresa de jogos e quem sabe junto com um pessoal eu não abro esse ano? Ah, e por que você deve acompanhar meus tutoriais? Bom, acho que é porque não terá nada a perder, eu normalmente pego coisas difíceis e tento deixa-las claras e fáceis de entender e divertida (Afinal, o que é sério às vezes se torna chato), então você pode ver esse post, e depois decidir se realmente vale a pena ou não ;D. Sem falar é lógico que caso não saiba de algo pode perguntar a vontade e nem precisa ser do tutorial, pois no ano passado recebi vários pedidos de ajuda que não tinha relação com o tutorial e sim com projetos de escolas e faculdades, envolvendo jogos com o Unity.

Após o primeiro tutorial (Que o seu termino coincidiu que a mudança do Unity 4 para o Unity 5  u.u), eu abri uma votação para saber de vocês, o que vocês queriam no próximo tutorial e a maioria votou na construção deu um jogo 2D com o Unity, porém com um nível mais avançado e com isso deu inicio a essa série de posts.

Para iniciar esse tutorial é bom que vocês tenham uma pequena noção do que teve no passado (Afinal, se esse é o intermediário, significa que o básico é um pré-requisito). Maaas, se você não quiser ver (Até porque algumas coisas mudaram), tudo bem, eu vou explicar de novo o que cada comando faz. Mas peço pelo menos para lerem a aula de introdução de conhecendo a Engine:

http://jogosindie.com/tutorial-de-unity-2d-conhecendo-a-engine/

Leiam também as 2 ou 3 primeiras aulas pra ajudar nesse tutorial.

Bom, para baixar o Unity, você pode ir pelo link: http://unity3d.com/pt/get-unity

E clicar na opção Download Gratuito (A versão gratuita dá para fazer praticamente tudo da versão paga, então deve servir para o seu jogo).

Após baixar e instalar (Avançar, avançar, avançar, avançar…). Você poderá acessar o Unity. Ao abrir, ele vai pedir para você se logar (Senão tiver ainda uma conta, basta criar).

Após logar, vai perguntar da sua licença. Aqui basta marcar a opção Personal Edition:

Ele irá dar umas informações da licença free (O que ele fala basicamente é que se você, ou sua empresa ou o para quem você trabalha seja uma universidade ou governo, tiver uma renda maior de 100 mil obamas, você é obrigado a usar a versão paga). Caso você ou a empresa/órgão para quem você trabalhe na construção do jogo não tiver uma renda anual maior que 100 mil dólares, basta dá agree:

Feito isto, basta começar a usar o Unity.

Pronto, a tela a seguir é a inicial do seu Unity com a sua conta, onde terá todos os jogos que você criou nesse pc com essa conta. Caso não tenha nenhum, basta dá um “Create a Project” (Criar um projeto):

Se tiver, basta clicar no “New” ali em cima ao lado do “Open” ^^

Ao criar um novo projeto, você vai definir o nome do projeto e o local onde ele será salvo. Também se lembre de marca a opção 2D (Afinal, nosso tutorial é para jogos 2D).

Feito isso, seu jogo irá carregar. Caso tenha marcado a opção 3D, bora lá arrumar:

Na sua aba Hierarchy deixe apenas o objeto Main Camera. Na Inspector  no script da câmera, troque para Solid Color:

(Por isso que pedi para ler pelo menos o post de conhecendo a engine do tutorial passado, pois lá eu explico o que é cada aba, como ativa-las e organizar da forma que achar melhor).

Na aba Scene marque a opção 2D e desmarque a opção Cenário:

Pronto, com isso seu jogo ficará com a aparência inicial dos jogos 2D. A organização das abas do Unity, fica a seu critério. Eu gosto sempre de deixar da  seguinte forma:

Mas independente da forma que você gostar, deixe sempre aberto as abas: Game, Scene, Hierarchy, Project, Inspector, Console, Animator e Animation, pois a gente vai usar bastante. Caso não encontre uma dessas abas, poderá ativa-la lá no meu principal na opção Window:

Bom, falei, falei ,falei falei e ainda não comecei o tutorial de hoje, acredita? Isso tudo a gente já viu com pequenas diferenças no Unity 4, mas o tutorial mesmo vai começar agora.

O que vamos fazer nesse tutorial, afinal? Bom, hoje será exclusivamente programação e script do personagem principal (Ou seja, para muitos a parte infernal, mas veja o lado bom, se você sobreviver a esse post, os próximos serão beeeeem mais tranquilos).

Nós vamos nesse tutorial criar basicamente 3 scripts:

1 – Uma script de Interface para o personagem (Digamos, que seja a cara do script, ou seja, o que os outros scripts vão ver do seu script do personagem principal)

2 – Um script Abstrato com as funcionalidades em comuns dos personagens ninja garoto e garota, como a movimentação, dano e experiência.

3 – Um script de Status (Contendo HP, MP e Ataque) do personagem.

O Script “concreto”, ou seja, aquele script final que usamos nos objetos, só será montado depois quando formos fazer cada personagem, por isso que eu digo que a aula de hoje será a mais chata, pois vamos criar algo sem ver praticamente o que está sendo construído (Chato, né?).

Mas sem choro, bora lá trabalhar para assim podermos avançar logo para a parte 2 do tutorial onde de fato criamos o personagem e o vemos em ação!

Bom, nossos scripts terão mais ou menos a seguinte aparência:

“Ahhhh, Carlos, estou gostando disso não, está começando a complicar, sou muito burro para entender isso”. Calma, calma, pequeno gafanhoto, isso de fato é um pouco complicado, tanto é que muita gente se forma nas faculdades e não sabem quando utilizar uma classe de Interface ou Abstrata (Não estou zoando, acho que quase ninguém da minha turma sabia).

Mas vou tentar clarear um pouco para vocês. Caso vocês tenham vindo do tutorial básico (Que é o recomendado), devem se lembrar de que para pegar algum script de um objeto fazíamos da seguinte forma:

var script = gameObject.GetComponent ();

Onde o método GetComponent vai pegar o Script com o nome NomeDoScript que tiver no objeto, certo? (Pode entender script como um componente do objeto na aba Inspector)
Agora pense comigo, antes nós só tínhamos um único script: “Player”, mas agora vamos ter “Personagem1”, “Personagem2”. Então qual nome que a gente vai por ali no lugar do NomeDoScript? Se colocarmos Personagem1 e tivermos usando Personagem2, vai dá erro de conteúdo nulo (Não existente). Difícil essa, né? Na realidade, nem tanto. É para isso que existe a interface, ou seja, é uma classe que apenas define quais os métodos que tanto Personagem1 quanto Personagem2 vai ter que ter. Nós chamaremos essa classe de IPersonagem (O I antes, é apenas um padrão, você pode por o nome que quiser, mas normalmente colocamos I antes de classes do tipo Interface, para ficar fácil visualizar). Ou seja, lá na chamada do script, poderíamos fazer apenas:

var script = gameObject.transform.GetComponent ();

Tanto faz ser o script Personagem1 ou o script Personagem2 que o objeto tem, pois ambos scripts usam a interface IPersonagem. Entenderam a ideia inicial da Interface? Facilita bastante, né? Ai digamos que na nossa Interface tem o método: “recebeDano”. Esse método também vai TER que existir para o script Personagem1 e Personagem2.
Bom, isso é a Interface. Vamos entender agora o que é a Classe Abstrata. A Classe Abstrata na realidade ela é muuuuito parecida com a classe concreta que já conhecemos (A que usamos normalmente). A diferença é que ela é um pouco de mistura de Interface com a classe concreta. Nela podemos criar os método e implementá-los (Coisa que não podemos na interface) e ao mesmo tempo podemos dizer quais outros métodos que não foram implementados terão que ser implementados nas classes filhas (Personagem1, Personagem2…). Porém a grande diferença para a classe abstrata para a classe concreta é que você nunca pode usa-la num objeto final, ou seja, ela serve apenas para ser herdada por outro script.

Para esclarecer melhor, vamos criar a classe Abstrata Jogador, onde vamos criar os métodos para movimentação e pulo. Ele é igual para qualquer personagem, correto? Então podemos implementar (Se alguém não souber o que significa implementar, é o mesmo que dizer escrever os códigos, dar vida, definir o que será feito) o método. Já o método responsável pelo ataque é diferente para cada personagem, pois um personagem ataca de perto e outro de longe, ou seja, esse método que é diferente nós dizemos que as classes filhas é que tem que implementar como esse método funciona.

Conseguiram entender melhor? Revisão:

Interface – Mostra para outras classes que não tem relação com o “jogador”, quais os comandos que podem ser executados. (Ou seja, serve para ajudar outras classes a interagir com as “classes filhas” da interface). Fazendo uma metáfora pense que a Interface é o gabinete do seu PC, você vê quais botões tem e pode interagir (métodos), mas não sabe quem é a placa mãe (A classe concreta) e nem o que ela faz por trás do gabinete (Interface).

Classe Abstrata – Implementa conteúdo comum e define quais métodos precisam ser implementados (Ou seja, define a estrutura das classes filhas e serve para ajudar a própria classe filha).

Com isso, podemos então dá inicio a construção dos scritps!

Bem, bem, bem, fim de enrolação, vamos lá. Nós vimos lá em cima a estrutura do nosso código e vamos criar seguindo aquela mesma ordem (Interface -> Classe Abstrata ->  Classe Concreta). A classe concreta não vai entrar no post de hoje, porém vamos criar 4 cases:

Interface – IPersonagem

Classe Abstrata – Jogador

Classe Concreta – Status

Interface – IHabilidade
OBS: É, vocês que me conhecem sabem que eu tento puxar tudo para o inglês, língua universal na programação, ou seja, seria ICharacter, Player, Status, ISkill. Porém nos tutoriais eu tento deixar tudo em português, então não estranhem se ao acaso eu esquecer de deixar algo em português e sair Player ao invés de Jogador.

Nessa parte de programação seria bom se você soubesse o básico de algoritmo. No primeiro tutorial eu criei um post extra onde eu explico sobre a programação, então seria muuuuuito bom que você lesse (Link: http://jogosindie.com/tutorial-de-unity-2d-extra-programacao/). Mas como eu sei que brasileiro é preguiçoso eu vou explicar aqui algumas coisas, porém sem grande detalhamento, afinal o post ficaria maior do que já vai ficar.

Bom, a primeira coisa que eu vou pedir a vocês é criar uma pasta chamada “scripts” no nosso projeto, onde ficaram os nossos scripts. Nesta pasta vamos organizar um pouco também, então dentro dela crie algo chamado jogador:

OBS: para quem não se lembra, clica com o botão direito em um canto vazio na aba Project e vai em Create >> Folder:

Pronto. Criado, vamos repetir o mesmo processo, clica dentro da pasta jogador com o botão direito e vai na opção Create >> C# Script. Aqui vamos criar nossos quatro scritps como combinamos:

Bom, classes criadas, agora vamos abrir o IPersonagem e definimos quais métodos ele terá que outras classes nossas também vão poder interagir.

Dá dois cliques em IPersonagem. Antigamente ele abririam o MonoDevelop, maaas (Graças a Deus), a Unity resolveu agora trabalhar com o Visual Studio, que é mais pesado, mas é bem melhor para ver erros, editar e pode finalmente pôr o “ç” no nosso script. Mas se você tiver com o MonoDevelop, poderá fazer tudo que a gente fará com o Visual Studio, menos por ç nos textos e comentários .-. .

Uma vez que o script for aberto, vocês terão essa linda visão e é aqui onde a diversão (Ou pesadelo para alguns) começa.

Bom, para você ai que andou pulando a aula do tutorial básico, como eu pedi, vai umas explicações básicas. Da estrutura de um código:

Os pacotes/namespaces ou classes externas do sistema, do Unity ou outros conteúdos que não foram criados por a gente, deverão ser indicados a sua posição chamando o seu pacote lá em cima com o using. Do contrário iremos ter que ao chamar outra classe dizer seu caminho completo. Não esquentem tanto com essa parte que ela é a de menos

A nossa classe é formada por variáveis e métodos. Em alguns casos você poderá ver também uma classe dentro de outra, mas não iremos trabalhar com isso nesse tutorial, então relaxem ai ;).

As variáveis são as informações da sua classe e os métodos são as ações. Exemplo:

Idade = informação = Variável.

Correr = Ação = Método.

Como eu falei a programação é algo universal então tem algumas regrinhas como nossas variáveis e métodos não podem ter acentos e ç. (Mas não significa que você não possa usa-los nos comentários ou textos, o que me faz ficar um pouco com raiva do MonoDevelop por não permitir essas coisas u.u).

Tanto classe, como método e variável elas podem ser do tipo:

public = todo mundo pode ver e acessar;

private  = só a classe que a possui pode ver e acessar;

protected = Apenas a classe atual e as classes filhas a ela, podem ver e acessar.

Se você não informar a visibilidade, ela será sempre private. Com exceção da interface, onde não declaramos a visibilidade dos nossos métodos, pois eles sempre serão public (Afinal, uma interface serve para que outras classes interajam com a atual, então não faz sentido ter métodos privados).

Eu falei ai sobre classe filha, mas afinal o que é isso? Bom, isso é o que chamamos de herança, ou seja, quando uma classe herda outra, ela leva consigo todas suas características (Métodos e Variáveis).

Nesse script já podemos ver isso ocorrendo, quando ele diz que IPersonagem é filha de MonoBehaviour:

E com isso todas os métodos e atributos de MonoBehaviour podem ser usados por IPersonagem.

Porém, nós não queremos isso, afinal IPersonagem será apenas um interface, ela não faz nada, apenas diz quais métodos as classes que a herdarem terão. Então vamos tirar esse class e essa herança e transforma-la em uma Interface:

Script: IPersonagem.cs

public interface IPersonagem {
    Status getStatus();
    void recebeDano(int dano);
}

No script acima troquei a informação class por interface e removi o :MonoBehaviour, para dizer que ele não irá herdar essas características.

Em seguida eu disse que todos os objetos que usarem essa interface terá dois métodos “getStatus()” que retorna a classe Status e recebeDano, onde informamos de quanto foi o dano e ele não retorna nada (void).

Mais uma vez uma explicação básica de programação sobre métodos. A estrutura de um método é da seguinte forma:

oTipoDeVariavelQueRetorna nomeDoMetodo();

Nosso método pode retornar tipos primários como int (Valores inteiros), string (textos), float (valores decimais), bool (Falsou ou Verdadeiro) ou classes/Interfaces (Status, IPersonagem, IHabilidade, GameObject…). Caso ele não retorne nada usamos o termo “void”. Nossas classes também podem receber parâmetros que serão usados na ação que iremos realizar:

void recebeDano(int dano);

Aqui estamos passando como parâmetro o dano sofrido que é do tipo inteiro, ou seja, ao usa-lo seria algo do tipo: recebeDano(10);

É um pouco complicado para quem não sabe programação, mas você pega o jeito, mas infelizmente não vou me aprofundar tanto nessas informações básicas nesse tutorial. Então se não entendeu algo, deixa ai a sua dúvida nos comentários, que em até 24h eu respondo ^^.

Bom, essa foi a nossa interface. Bem simples por hora, não é mesmo? Agora vamos criar a nossa maior classe de hoje, a de Jogador, mas se você já viu o tutorial, básico já sabe exatamente o que iremos fazer com pequenas modificações. Então salve essa interface ai (Ctrl+s) e abra o script Jogador que está ali ao lado:

Bom, essa será nossa classe Abstrata, então a primeira coisa é dizer que ela é uma classe abstrata:

Em seguida, vamos adicionar a interface IPersonagem após a classe MonoBehaviour. Se você reparar já vai aparecer algumas mensagens de erro dizendo que há alguns métodos da interface IPersonagem não foram implementados:

Então bora fazer as suas chamadas por enquanto sem implementa-los ainda:

Script: Jogador.cs

    public Status getStatus() {
        throw new NotImplementedException();
    }

    public void recebeDano(int dano) {
        throw new NotImplementedException();
    }

(Ele cria sozinho se você clicar em Show potencial fixes ou Ctrl+ e depois clicar em implements interface).

Depois a gente altera esses métodos.

A primeira coisa que eu vou fazer é criar as variáveis da classe:

Script: Jogador.cs

    protected Status status;            //Classe com informações de HP, MP, Ataque, EXP, Nivel do personagem
    public Animator animator;           //Classe do próprio Unity responsável pela troca de Animação
    public float velocidade;            //Velocidade que o personagem anda
    public float forcaPulo;             //A força que será aplicada ao personagem pular
    protected bool direita = true;      //Lado para qual nosso personagem esta virado
    public GameObject chaoVerificador;  //Objeto que usaremos para saber se nosso objeto esta encostado no chão
    protected bool estaNoChao;          //Variável que informa (true) se nosso personagem estiver no chão
    public IHabilidade[] habilidades = new IHabilidade[3]; //As 3 habilidades do personagem

Vocês podem reparar que algumas aí estão como public. O motivo é pelo fato de que iremos informar os dados direto pela aba Inspector no Unity ao invés de ser pelo script. Do contrário, todas essas classes seriam privates ou protected, pois outras classes não iriam interagir com elas. Caso você queira algo mais “seguro” pode deixar tudo como protected e antes usar a tag [SerializeField].

Qual a vantagem de usar o public então? Bom, ele é mais prático devido ao fato de ser possível ser usado no Inspector e segundo umas discussão que eu vi, possui uma performance melhor do que você ter que chamar o objeto via script.

Quem acompanhou o primeiro tutorial já conhece bem do que essas tutoriais se tratam, mas vamos lá as explicações:

  • status =  vai conter as informações da evolução do jogador ao longo do jogo;
  • animator = É uma classe do próprio Unity responsável pela transição de uma animação para outra, vocês vão entender melhor isso no próximo post ou lendo o tutorial básico;
  • velocidade = A velocidade com a qual nosso personagem irá se locomover;
  • forcaPulo = A força aplicada no pulo do personagem, ou seja, quanto mais força, mais alto seu personagem vai;
  • direita = Informa para qual lado nosso personagem está virado, se para esquerda (false = falso) ou para direita (true = verdadeiro);
  • chaoVerificador = será um objeto na nossa scene que fica abaixo do personagem. Se existir um chão entre o personagem e esse objeto, então significa que o personagem está encostado no chão;
  • estaNoChao = Guarda justamente a informação se ele está ou não no chão;
  • habilidades = uma lista com 3 classes que implementem a interface IHabilidade.

Uma lista serve para guardar mais de um tipo de lado. Pense uma lista de livros, lista de itens em uma compra. É mais ou menos essa a ideia. E a sua estrutura é como vimos acima.

NomeDoTipo[] = Indica uma lista do tipo NomeDoTipo

new NomeDoTipo[tamanho] = Indica o tamanho dessa lista

Vão existir outros parâmetros que iremos criar mais na frente, como por exemplo, uma variável do tipo booleana (bool) para verificar se o personagem pode ou não atacar, mas isso iremos fazer posteriormente, quando criamos os personagens.

Então o que ambos os personagens terão em comum é o método mover e a declaração do método abstrato atacar. “atacar” será um método abstrato, por que a forma de ataque de cada personagem será diferente, mas este método TEM que existir em ambas as classes filhas, por isso a declaramos como abstrata (Não implementamos agora, mas obrigatoriamente as classes filhas tem que implementar):

Script: Jogador.cs

    void mover() {
       
    }

    protected abstract void atacar();

Caso reparem meus métodos iniciam com letra minúscula e os do Unity com letra maiúscula. Na programação normalmente utilizamos o padrão CamelCase, que é o fato de escrever palavras com letra maiúscula quando houver separação. Exemplo:

ataqueRapido();

ataqueMuitoRapido();

ataqueNaVelocidadeDaLuz();

O Unity também respeita esse padrão, porém ele trabalhar com UpperCamelCase, onde a primeira letra já inicia com letra maiúscula. Já eu e a maioria dos locais que você for ver, trabalham com lowerCamelCase, onde a primeira letra é minúscula. Fica a seu cargo decidir qual padrão seguir ou se quiser seguir outro padrão como o undercore, onde a escrita é da seguinte forma:

ataque_rapido();

ataque_muito_rapido();

ataque_na_velocidade_da_luz ();

Cooontinuando, vamos ao método Update, adicionar os outros dois métodos:

Script: Jogador.cs

    void Update() {
        mover();
        atacar();
    }

Declaramos aquele método atacar como abstrato, porque já queremos fazer a chamada a ele nessa classe. Caso apenas o criássemos na classe filha, a classe mãe não saberia da existência desse método na classe filha.

Continuando… O método Start ele é chamado uma única vez quando o objeto é criado. Já o método Update ele executado a cada frame do seu jogo (Ou seja, o tempo todo) enquanto o objeto existir. Desta forma dentro do Update você vai colocar tudo aquilo que você quer que o jogador possa fazer enquanto o jogo estiver rodando.

Agora vamos implementar o método mover. A primeira coisa que eu vou fazer é verificar se o personagem está apertando a tecla para direita, para então mover o personagem:

Script: Jogador.cs

   void mover() {
        if (Input.GetAxisRaw("Horizontal") > 0) {
            if (!direita)
                inverter();

            transform.Translate(Vector3.right * velocidade * Time.deltaTime);

            direita = true;
        }
    }

Bora lá as explicações para quem pulou o tutorial básico.

Um If (SE) é uma condição. Ou seja:

SE (CONDIÇÃO FOR VERDADEIRA) {

                EXECUTO O CODIGO DAQUI DE DENTRO

}

Também pode aparecer da seguinte forma:

SE (CONDIÇÃO FOR VERDADEIRA) {

                EXECUTO O CODIGO DAQUI DE DENTRO

} SENÃO {

                EXECUTO O CODIGO DAQUI DE DENTRO

}

O Input é uma classe do Unity com métodos estáticos, ou seja, que podem ser acessadas por outros objetos sem precisar declara-lo em uma variável (Ex: Input input = new Input). Esses métodos servem para pegar algumas informações dos botões ou outros dados de entradas usados pelo jogador.

Você pode ver quais são os Inputs do seu jogo indo lá no Unity no menu Edit >> Project Settings >> Input:

O método Input.GetAxisRaw(“Horizontal”) irá retornar valor 1 se a pessoa clicou nos botões d ou a setinha ->. Ou seja, se o jogador apertou então Horizontal será 1, logo é maior que 0, por tanto entrará no if.

Neste if temos mais um if, para verificar para qual lado nosso personagem está virado. Se ele estiver no sentido contrário, ou seja, apertamos para ele andar para direita, mas ele está virado para esquerda, então invertemos a direção do personagem através do método inverter, que já já eu o explico.

A “!” serve para ser a negação da condição. Ou seja, se a condição for verdadeira e você está negando, então ela se torna falsa. Se a condição for falsa e você a está negando, então ela se torna verdadeira.

Exemplo:

Quando Valor = true;

Valor; (Valor é true)

!Valor; (Valor é false)

—-

Quando Valor = fase;

Valor; (Valor é false)

!Valor; (Valor é true)

A variável transform lá no método mover, nada mais é do que o transform do seu objeto lá na aba Inspector:

Ou seja, podemos acessar as informações de posição (position), rotação (rotation/eulerAngle) e escala (scale) do nosso objeto, tal como move este objeto, que é justamente o que vamos com o método Translate.

Aqui dizemos que nosso personagem vai andar 1 ponto para a direita (Vector3.right = (1, 0, 0)), vezes a velocidade que definirmos, vezes quantos segundos passaram desde o ultimo frame. Esse Time.deltaTime nada mais é do que um controle que usamos que todos os computadores funcionem mais ou menos na mesma velocidade, no tutorial básico eu faço um exemplo claro disso. Sendo assim, mesmo que seu computador rode mais frames por segundo, seu personagem irá se mover na mesma velocidade que outro computador mais humilde.

Por fim, naquele método, dizemos a direção que nosso personagem está virado (direita = true).

Bom, agora explicando o inverter, o que nós vazemos é trocar a escala do personagem no eixo X de positiva para negativa da seguinte forma:

Script: Jogador.cs

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

Ai, você fala, “Pow Carlos, não é mais fácil, apenas rotacionar o personagem para o outro lado?”. Sim, sem dúvida é, mas o Unity tem um bug que se você fizer isso, ele ignora de rotacionar os colisores do seu personagem. Se seu jogo todos os colisores forem centralizados, beleza. Mas se você tiver algum colisor mais a frente do herói, ao inverter utilizando a rotação, o colisor ao invés de ficar na frente do personagem, ele ficará nas costas, o que será um problema, que podemos evitar desde já.

Pronto, feito isso, agora vamos fazer o inverso para o lado esquerdo.

Script: Jogador.cs

    void mover() {
        if (Input.GetAxisRaw("Horizontal") > 0) {
            if (!direita)
                inverter();

            transform.Translate(Vector3.right * velocidade * Time.deltaTime);

            direita = true;
        }

        if (Input.GetAxisRaw("Horizontal") < 0) {
            if (direita)
                inverter();
            transform.Translate(-Vector3.right * velocidade * Time.deltaTime);
            direita = false;
        }

É basicamente a mesma coisa, porém no GetAxisRaw, eu verifico se foi clicado na tecla A ou na setinha Ainda não entendeu porque Vector3.right e -Vector3.right? Esse vetores na realidade só retorna x =1 e x = -1.

Caso esteja usando a versão 5.4 ou superior, sempre use o Vector3.right positivo para os dois lados (Inclusive nos próximos scripts de movimentação dos inimigos), pois nessa versão ao mudar a escala para negativa, funciona semelhante a rotacionar o objeto

Então se o nosso personagem está na posição 8 no eixo de X, e a gente que ir para a esquerda, então ele tem que diminuir o valor de x recebendo valores negativos. Se ele quer ir para a direita, então tem que aumentar o valo de x, recebendo valores positivos.

Bom, para finalizar basta apenas a gente fazer a funcionalidade do pulo. O que vamos adicionar ao nosso script é apenas essas pequenas linhas:

    estaNoChao = Physics2D.Linecast(transform.position, chaoVerificador.transform.position, 1 << LayerMask.NameToLayer("Piso"));
        if (Input.GetButtonDown("Jump") && estaNoChao) {
            GetComponent().AddForce(transform.up * forcaPulo);
        }

Agora vamos destrinchar esse código ai. O Physics2D é uma classe do próprio Unity que serve para trabalhar com a Física 2D do jogo. O método Linecast nada mais faz do que traça uma linha da posição 1 (transform.position) a posição 2 (chaoVerificador.transform.position) e verificar se tem algum objeto com a Layer “Piso” (1 << LayerMask.NameToLayer("Piso")). Caso tenha algum objeto com essa layer, o método retornar true (verdadeiro) para a variável estaNoChao. Em seguida temos uma condição, no qual verificamos se o jogador apertou o Botão “Jump” (Tecla Espaço, você pode troca-la indo lá em Edit >> Project Settings >> Input). O caractere “&&” serve como um “E” e o caractere “||” serve como um “OU”. Então:

if (Input.GetButtonDown("Jump") && estaNoChao)

SE (o jogador apertou o botão “Jump” E o personagem está no chão) ENTÃO EXECUTA O CÓDIGO.

No código: GetComponent().AddForce(transform.up * forcaPulo);, nada mais estamos pegando o componente Rigidbody2D no objeto atual com o script e aplicando a ele uma força (forcaPulo) na direção para cima do personagem (transform.up). Por que aqui não precisamos aplicar o Time.deltaTime? Por que essa ação irá ser realizada apenas uma vez por pulo e não algo continuo (O Input.GetButtonDown retorna true apenas no primeiro frame que você apertou, ou seja para ele retornar true em outro frame, tu tem que apertar de novo, só que ai o personagem já não estará mais no chão ;)).

Caso, você tenha achado muito corrido ou difícil de entender, peço que leia o tutorial básico a parte de movimentação, pois temos dois posts inteiros focados só nesse método lá no tutorial básico. Por isso que não estou detalhando tanto assim.

E com isso terminamos esse script? Nããããão, ainda temos lá os outros método não implementados, esqueceram? Bom, no getStatus, é bem simples, basta por:

Script: Jogador.cs

    public Status getStatus() {
        return status;
    }

E com isso ele irá retornar a classe com o status do personagem atual. Isso é o que chamamos de Get na programação. Bem simples, né?
O outro método que precisamos fazer é um pouco mais complicado, mas nada para se preocupar ainda. Mas antes de fazer isso, temos que alterar essas informações lá na Classe Status. Então abre lá a classe Status:

Bom, essa classe ela não vai herdar nada do MonoBehaviour, então podemos remover essa herança:

Em seguida vamos criar os atributos (Variáveis):

Script: Status.cs

    private int hp;          //Total de vida atual do personagem
    private int hpMax;       //Total de vida máxima do personagem
    private int mp;         //Total de pontos de mágia atual do personagem
    private int mpMax;      //Total de pontos de mágia máxima do personagem
    private int ataque;     //Poder do ataque
    private int exp = 1;    //Total de experiencia
    private int nivel = 1;  //Nível atual do personagem

Defina tudo como private, pois queremos evitar que alguns valores sejam alterados de forma incorreta, exemplo eu tenho 10 de vida, mas minha vida máxima é 7. Bom feito isso, vou criar o construtor desse método, que nada mais é que aquela declaração que fazermos ao criar um novo jogo “new Status();”.

Porém eu quero que nesse new Status, eu possa passar alguns parâmetros então faço:

Script: Status.cs

    public Status() {}

    public Status(int novoHP, int novoMP, int novoAtaque) {
        this.hpMax = this.hp = novoHP;
        this.mpMax = this.mp = novoMP;
        this.ataque = novoAtaque;
    }

Se reparar criei dois construtores, um vazio para poder fazer um:

Status status = new Status();

E um onde eu já passo algumas informações de quanto será o HP, o MP e o ataque do personagem:

Status status = new Status(10, 5, 3);

Ou seja:

Status status = novo Status(10 de vida, 5 de mágia, 3 de ataque);

Bom, agora é hora de criar os gets (Os métodos que retorna os valores do nosso status):

Script: Status.cs

    public int getHP() {
        return hp;
    }

    public int getHPMax() {
        return hpMax;
    }

    public int getMP() {
        return mp;
    }

    public int getMPMax() {
        return mpMax;
    }

    public int getAtaque() {
        return ataque;
    }

    public int getExp() {
        return exp;
    }

    public int getNivel() {
        return nivel;
    }

Depois disso criamos os setters de algumas delas (Setters são os métodos responsáveis por setar/definir os valores):

Script: Status.cs

    public void setHP(int hp) {
        if (hp > this.hpMax)
            hp = this.hpMax;
        this.hp = hp;
    }

    public void setMP(int mp) {
        if (mp > this.mpMax)
            mp = this.mpMax;
        this.mp = mp;
    }

    public void setHPMax(int hpMax) {
        this.hpMax = hpMax;
    }

    public void setAtaque(int ataque) {
        this.ataque = ataque;
    }

    public void setExp(int exp) {
        this.exp = exp;
        this.nivel = (int)System.Math.Ceiling(exp / 100.00);
    }

Aqui já mudou um pouco, estou começando a tratar os códigos com um padrão mais real de programação. Se reparar eu uso o mesmo nome tanto no parâmetro do método, quanto na variável da classe. Então para diferencia-las nós usamos o this.nomeDaVariavel, para as variáveis da classe e usamos apenas nomeDaVariavel para as variáveis locais do método. Caso não exista variável local e você não use o this, ele ainda sim usará a variável da classe.

Também fiz um esqueminha para dividir o nível do jogador, onde eu divido a experiência por 10 e o resultado eu pego o maior valor inteiro para ser o nível. Exemplos:

5/10 = 0.5 = maior valor inteiro é 1 = Nível é 1
11/10 = 1.1 =maior valor inteiro é 2 = Nível é 2
...
Ou seja, é como se nosso personagem subisse de nível a cada 10 pontos de experiência. Aqui a experiência não vai alterar em nada o hp, mp e ataque do personagem (mas fique a vontade para fazer seu próprio estilo), porém ele servirá para liberar as habilidades de seu personagem.

E para finalizar vou criar alguns métodos, um responsável por adicionar vida, outro por causar dano, um para recuperar pontos de magia, outro para perder pontos de magia e outro para ganhar experiência:

Script: Status.cs

    public void sofrerDano(int dano) {
        this.hp -= dano;
        if (this.hp < 0)
            this.hp = 0;
    }

    public void recuperaHP (int valor) {
        this.hp += valor;
        if (this.hp > this.hpMax)
            this.hp = this.hpMax;
    }

    public bool usaMagia(int mp) {
        if (this.mp < mp)
            return false;

        this.mp -= mp;
        return true;
    }

    public void recuperaMagia(int valor) {
        this.mp += valor;
        if (this.mp > this.mpMax)
            this.mp = this.mpMax;
    }

    public void adicionaExp(int valor) {
        exp += valor;
        nivel = (int)System.Math.Ceiling(exp / 100.00);
    }

Bora explicar os métodos de uma forma mais rápida, para ver se vocês já estão pegando o jeito com a programação (E porque eu estou cansado de escrever também >.<). sofrerDano – Reduz da vida atual (hp) do personagem, o dano causado. Se o hp ficar negativo, então o deixamos zerado; recuperaHP – Adicionamos a vida atual (hp) do personagem, o valor informado. Se o hp ficar maior que o HP Máximo (hpMax) do personagem, então o hp recebe hpMax; usaMagia – Primeiro verificamos se o personagem tem MP suficiente para usar a magia. Senão tiver, retornamos false, se tiver, apenas reduzimos do mp atual o valor gasto; recuperaMagia – é semelhante ao recuperaHP; adicionaExp – Apenas adicionar o valor ao exp atual e atualiza o nível;

OBS: Não sei se já repararam a diferença entre =, +=, -=, *=, mas caso não ai vai uma explicação: Digamos que temos uma variável “x = 2” então = -> Atribui o valor a variável. Ex: x = 5, agora x é 5
+= -> Soma ao valor existente. Ex x += 10, agora x é 12
-= -> Subtrai ao valor existente. Ex x -= 10, agora x é -8
*= -> Multiplica o valor existente Ex x*=100, agora x é 200

Voltando... Só precisamos de mais um único método para terminamos a classe Status:
Script: Status.cs

    public bool estaMorto() {
        return this.hp == 0;
    }

Bem simples, né? Esse método verifica se o personagem está morto (true = morto | false = vivo), que é quando seu hp for igual 0.

Bom, terminamos essa classe, agora vamos voltar lá ao Jogador e terminar aquele método que ficou faltando. No método recebeDano, vamos fazer o seguinte:

Script: Jogador.cs

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

Sim, por hora será apenas isso, depois que definimos a morte do personagem, é que iremos nesse mesmo método realizar a ação que será feita ao morrer.

Acabou mais um script o/. Cansou, né? Também estou morto. Bom vá lá tomar um cafezinho para a gente finalizar esse tutorial.

Já está pronto? Então bora lá, que agora falta pouca coisa. O próximo passo é implementar a interface IHabilidade e terminaremos por hoje. Então clica lá na IHabilidade:

E aqui vamos fazer aquele mesmo esquema de transforma a classe em interface:

Script: IHabilidade.cs

using UnityEngine;
using System.Collections;

public interface IHabilidade {
}

O que essa interface terá como método? Bem simples, apenas três coisas: getCustoHabilidade (Que é o MP gasto), setPersonagem (Para podermos acessar alguns conteúdos desse script, como a sua posição e a física) executar (Que realiza o que a habilidade faz):

Script: IHabilidade.cs

using UnityEngine;
using System.Collections;

public interface IHabilidade {

    void setPersonagem(GameObject personagem);
    int getCustoHabilidade();
    void executar();
}

Simples assim. É desta forma que eu termino esse primeiro post do tutorial o/.

Nesse mega post criamos a interface que será usada para inimigos interagem com nosso personagem, a classe abstrata com os movimentos do jogador, a classe responsável pelo status do personagem e a interface responsável pelas habilidades, além de revisar alguns comandos do Unity e algoritmo.

Ao pessoal que não leu o tutorial básico, peço mais uma vez que leiam, isso vai ajudar bastante vocês e nos próximos posts eu não pretendo ficar parando tanto para explicar o que eu já expliquei antes (Não que eu não vá fazer, mas não tão detalhado quanto fiz antes, afinal aqui é a ideia é fazer algo com um nível de dificuldade maior).

No final deste post vai ter as 4 classes que criamos e o arquivo do projeto para download, contendo um cenário com uma fase Teste apenas para vocês verem o que foi criado ^^.

Nooossa, estou enferrujado. Cansei com esse tutorial, foram mais de 15h escrevendo e 28 páginas no Word >.

Índice Tutorial Intermediário

Download do Projeto

Download do Jogo

 

Índice Tutorial Básico

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

39 comments

  1. Victor Hugo disse:

    Carlooss!!! Quanto tempo!!! Que nostalgia lendo seu tutorial, pelo menos o inicio
    Então… Esse é o tutorial que você disse que ia lançar fim do mês né? *-*
    Vou baixar o unity de novo, to a um tempo sem mexer nele, e acredito que ja tenha lançado uma versão mais recente.

    Muito bom ler seus tutoriais Carlos ^^ … uma dúvida, se seu nome é Carlos Lessa, o que significa o W? hsausahusahuas

    • E aê Victor o///

      Rapaz, esse é o tutorial que eu prometi para fevereiro do ano passado, antes de me afastar, mas tem umas modificações. Não lembro exatamente como seria, mas removi outras e adicionei outras que achei mais interessante para o tutorial. O que ficou de fora, irei explorar melhor em outros posts após o tutorial como inventário e itens criados através de uma classe ScriptableObject.

      Maaaaas quando ao meu nome, ele não possui nem W. e nem Gama. o Gama vem do nome da minha namorada. E quanto ao W, é um mistério que apenas quem me conhece a mais de 7 anos sabe o que realmente significa e olhe lá =P.

  2. alvaro disse:

    Carlos pode fazer as pazes com o Mono ele foi atualizado e aceita acentos e agora vc pode até escrever çalçiçha nele kkk.

    • Isso é uma ótima notícia =P

      Se eu tiver ele instalado aqui, vou testar na sexta. Mas ainda acho que o Visual Studio deve estar na frente, com as funções de identificação de erros e auto-preenchimento. Porém, não custa nada experimentar 😉

  3. Victor Hugo disse:

    Carlos!!! Comecei agora a fazer seus tutoriais rsrs, tava esperando lançar uma certa quantidade para não ficar ansioso pelo próximo rsrs, vamos la, eu to um pouco perdido quanto a organização do script, nos scripts de interface o “update” e o “start” realmente somem?(eu os deletei)
    e no script status, tem alguma ordem que deva ser seguida? ou simplesmente posso sair colocando tudo um embaixo do outro?
    Ex.:
    void start(){}
    void update(){}
    public Status(){}
    public int “…”(){}
    public int “…”(){}
    public int “…”(){}
    public void “…”(){}
    public void “…”(){}
    public void “…”(){}

    • Victor Hugo disse:

      hmm… acabei de reparar que você disponibilizou o download do projeto, agora olhando o scrip do status eu meio q me perdi haha, o update e o start não servem pra nada? ‘-‘

      • Os métodos Start/Awake/Update/FixedUpdate/OnTriggerEnter2D/OnCollisionEnter2D… são exclusivos da classe MonoBehaviour.

        E caso você tenha reparado a gente herdou essa classe na classe Statatus. O MonoBehaviour é utilizando quando queremos atribuir uma classe a um objeto lá no Unity, porém a classe Status ela não está atrelada a um objeto do Unity e sim a classe Jogador ^^

    • Victor Hugo disse:

      só se utiliza o start e o update na classe abstrata?

    • E aê Hugo ^^

      Vamos lá!

      Sim, na Interface nós apenas queremos colocar os métodos exclusivos daquele grupo de classes que outras classes irão acessar. O método Start e Update não são acessados por outras classes, por tanto ele não será adicionado aqui ^^

      Quanto a ordem dos métodos tantos faz. Você pode deixar como quiser. Normalmente o pessoal faz na seguinte ordem:

      1 – variaveis
      2 – Construtores
      3 – Getters e Setters
      5 – Demais métodos

  4. Hugo E.R. Ferreira disse:

    Ufa, esse tutorial foi grande!
    Carlos, essa coisa de colocar uma escala negativa e girar o personagem é muito estranho. Nunca tinha tentado colocar uma escala negativa, tô viajando nisso até agora.

    Me aconteceu um erro quando tentei compilar com a linha:

    throw new NotImplementedException ();

    Apareceu: O nome de namespace ou o tipo ‘NotImplementedException’ não pôde ser encontrado. Precisa de uma diretiva using ou de uma referência de assembly.

    Ainda bem que não foi necessária no código final.

    • E aê Hugo. O NotImplementedException, ele na realidade usa o using system; lá no inicio do código. Mas como não precisamos, podemos tirar tanto um quanto o outro.

      Quando a escala negativa é o mesmo que acontece com alguns editores de imagens (Acho que no photoshop também), que você pode inverter o lado da imagem alterando seu tamanho para o outro. Mas é estranho mesmo. A rotação é mais lógica, porém é comum dar alguns problemas com o collider.

  5. Breno Santin disse:

    Carlos beleza? não entendi sobre esse terceiro parâmetro do LineCast.
    estaNoChao = Physics2D.Linecast(transform.position, chaoVerificador.transform.position, 1 << LayerMask.NameToLayer("Piso"));

    Por que usar esse 1 ? achei que só deveria especificar o nome da layer.

    • o LayerMask.NameToLayer(“Piso”) retorna o valor em bit que representa a mascara (2, 4, 8, 16, 32…). O:

      1 << X é a representação do Unity para trabalhar bitmask. Ou seja o 1 << é um comando utilizando para identificar a conversa para a mascara ^^

  6. Hayako disse:

    Ei carlos!,estou com um problemao aqui cara,eu começo a escrever as linhas
    Exemplo:
    public interface IPersonagem {
    Status getStatus();
    void recebeDano(int dano);
    }
    E fica dando erro,e isso acontece com os outros scripts(Jogador,Status,IHabilidade)
    como eu posso consertar isso ?
    OBS:Nao sei nada sobre programaçao,minha area é o Game Design 😉 !!

    • Qual a mensagem de erro que fica dando Hayako? Pode ser muita coisa, inclusive erro de instalação.

      Existe alguma mensagem de erro?

      OBS: Muito legal ser Game Design. Por isso é bom você saber um pouco de cada área, mas não precisa se aprofundar tanto em outras áreas.

  7. Hayako disse:

    Eu coloquei apenas o primeiro codigo,que seria : public interface IPersonagem {
    Status getStatus();
    void recebeDano(int dano);
    }
    Aparece os seguintes erros : Severity Code Description Project File Line Suppression State
    Error CS0531 ‘IPersonagem.Start()’: interface members cannot have a definition Key of The Castle.CSharp C:\Users\ygorn\Desktop\Key of The Castle\Assets\Scripts\jogador\IPersonagem.cs 9 Active

    Erro 2 : Severity Code Description Project File Line Suppression State
    Error CS0531 ‘IPersonagem.Update()’: interface members cannot have a definition Key of The Castle.CSharp C:\Users\ygorn\Desktop\Key of The Castle\Assets\Scripts\jogador\IPersonagem.cs 14 Active.
    Espero que de para entender :D,e por favor me ajuda 🙁

    !Obrigado desde já pela atenção! 😀 :v

    • huuuuum, bad news… O erro:
      Severity Code Description Project File Line Suppression State

      Não é um problema do Unity em si, mas sim do Visual Studio. Talvez vá ser preciso reinstalar o Visual Studio para ver se TALVEZ, volte. Esse probleminha é meio chatinho.

  8. Hayako disse:

    Ok vou reinstalar o Visual Studio

    Obrigado novamente pela atenção 😀

    OBS:Infelizmente eu ainda irei fazer muitas perguntas,espero que voce tenha paciencia comigo u.u

  9. Hayako disse:

    Hey Carlos,estou com mais um problema na programação(como sempre),bom esta acontecendo o seguinte erro :
    Assets/Scripts/Player.cs(21,9): error CS8025: Parsing error

    OBS: Eu ja desinstalei o Visual Studio e reinstalei 😀

    • Parsing error, é falha na formatação de algum método ou até mesmo da classe. Verifica se não está faltando algum “}”. Qualquer coisa manda o código para eu dar uma olhada ^^

  10. Hayako disse:

    Bom estava vendo que neste tutorial voce vai usar dois personagens,e por isso tem aquelas coisas de(IPersonagem,IHabilidade etc..)e no meu jogo eu vou usar apenas um personagem,entao fui buscar os comandos em outro tutorial seu,nao sei se os comandos de lá vao funcionar aqui no meu unity pois eu to com o Unity 5,mas caso voce queira dar uma olhada no codigo,que voce provavelmente vai reconhecer
    Codigo:
    using UnityEngine;
    using System.Collections;

    public class Player : MonoBehaviour {

    public float velocidade;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
    void Movimentacao() {
    if (Input.GetAxisRaw(“Horizontal”) > 0) {
    transform.Translate (Vector2.right * velocidade * Time.deltaTime);
    }
    }
    Obrigado novamente,e caso tenha alguma forma para fazer esse codigo na nova versão do Unity,por favor me fale 😀 !!!

    • Pode sim Hayako. Da forma como você fez, ele irá considerar apenas um lado. Agora tem que fazer o mesmo para o outro ^^
      Minha recomendação no caso é que inicie pelo tutorial básico mesmo. Só ignore a parte UI, pois não usamos mais aquele modelo

  11. Hayako disse:

    Entao,se eu fiz para direita eu tenho que fazer para esquerda agora,certo?
    Obrigado novamente 😀

  12. Doug disse:

    Demorei dois dias pra ler tudo, um terceiro pra compreender. Ajudaria se colocar um resumo no final!

  13. Olá, poderia postar com fica o script ” Jogador ”
    Eu copiei tudo igualzinho e tem alguns erros, eu acho que é por causa que o meu Unity esta em outra versão. Versão 5.3.4

    Gostaria de saber como eu poderia fazer para concertar, se tem algum site que eu posso olhar para saber como trocar algumas programações para funcionar igual em outras versões.

    Aproveitar aqui para deixar um obrigado por postar isso, esta me ajudando bastante a compreender a lógica de programação, além do código em si.

  14. Luiz Hennrique Saillot Neves Valente disse:

    Cara simplesmente Parabéns! pelos tutoriais! cara obrigado por dedicar seu tempo a faze-los, pois, até agora o senhor tem me ajudado muito.
    O bom de seus tutorias é que são escritos e com fotos(print’s) isso facilitou tudo pois minha internet e de baixa qualidade e com isso possibilitou com que eu pudesse aprender um pouco sobre Unity.
    Resumindo Obrigado.

  15. Coloquei o mesmo código que estava no seu arquivo e funcionou. Infelizmente eu não olhei antes de testar o que tinha de diferente, o programa atualizou automaticamente e quando eu vi já era ‘-‘
    Obrigado por responder!

  16. rafoso disse:

    Nice tutorial man!! vou acompanhar !!

  17. E ai cara, suave? Então, to tentando recriar alguns movimentos do Mega Man X para estudar um pouco movimentação, e me deparei com a seguinte situação:

    – O botão de pulo permite você pular “baixo”, “médio” e “alto”. Algo tipo, se eu aperto o botão de pulo e solto, ele vai pular baixo, caso eu apertar o botão e soltar 1 segundo depois, ele vai pular médio, e caso eu apertar o botão por 2 segundos ou mais, ele vai pular alto (como se fosse o pulo completo).
    O problema é que já tentei usar o GetButton, GetButtonDown junto com variáveis que pegam o tempo do botão apertado, mas não consigo de forma nenhuma fazer esse “controle” da força do pulo.
    – Outra situação foi criar o método do Dash, em qual eu usei um Coroutine. O único problema é que não consigo cancelar esse Dash, nem setando algum botão/tecla com o Stop Coroutine.

    Bem, é isso. Se você puder me ajudar ou dar alguma dica, ficarei agradecido.

    • GetButton -> retorna true enquanto o jogador estiver segurando o botão

      GetButtonDown -> retorna true apenas no momento que a pessoa aperta o botão (Não fica repetindo true, enquanto tiver segurado)

      GetAxis -> Retorna a força aplicada ao botão.

      No seu caso, acredito que vai usar o GetAxis. Se você apertar bem rápido ele deve retornar um valor baixo 0.2, mas se apertar por muito tempo ele retornará um valor completo 1.0 ^^

      Em Edit >> Project Settings >> Inputs, você poderá adaptar melhor a sensibilidade desse botão, o quão rápido ou lenta será a resposta ^^

  18. Reginaldo Simon Bonaldi disse:

    Nao consigo colocar essa linha no pulo
    GetComponent().AddForce(transform.up * forcaPulo);
    diz que nao contem o Addforce. uso unitu 5.3

  19. Alessandro de Souza disse:

    Olá Carlos blz, o meu Unity 5.1 está dando o seguinte erro ( A classe ‘jogador’ não pode ter varias classes base ‘Unity Engine Monobehaviour’ e ‘Personagem’), por favor me ajuda ai estou começando e se eu conseguir seguir este tutorial inteiro ganho um lugar do lado dos programadores da minha esmpresa.Obrigado.

    • Cara, você vai ter muito trabalho se for usar esse tutorial.

      Ele está já desatualizado com o novo Unity e o blog deu algumas broncas com as tag < e > u.u

      Mas se quiser insistir a bronca que está tendo ai no seu projeto é que Personagem está como uma classe e não uma interface. Cada classe só pode herdar uma unica classe, mas pode ter várias interfaces.

      Ou seja, ou tu transformar sua classe “Personagem” em uma interface, ou caso seu Personagem já herde MonoBehaviour, então apenas remova o MonoBehaviour da classe jogador, ficando:

      class jogador: Personagem {

      }

      Minha recomendação mesmo é que tu baixe o código do projeto. Acho que será melhor se basear por ele do que pelo post

  20. Alessandro de Souza disse:

    Boa noite Carlos, obrigado pelo retorno, vou baixar o código e seguir com o tutorial.

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!