[Unity] Controlando animações com Animator

Introdução:
Olá pessoal, como vão? Hoje estou aqui para ensinar como controlar animações utilizando o componente de controle de animação da Unity (Animation Controller) e para falar um pouco sobre o site Mixamo.com.



Primeiramente, gostaria de convidá-los a conhecer o já citado mixamo.com, um website voltado à tecnologia 3D que visa facilitar a vida dos desenvolvedores de games, disponibilizando um acervo fantástico de animações pré-prontas que possuem uma movimentação bem fluída e com configuração de parâmetros (como espaçamento entre braços, intensidade de movimentos e etc) na própria interface, tudo isso de graça bastando um rápido cadastro no site e estar com o Adobe Flash atualizado!

Na aba "Characters" você encontra alguns personagens já disponíveis pelo site para que você possa utilizar em seu projeto, basta escolher um:



Você também pode fazer o upload do seu próprio modelo (ou de outro site), bastando clicar no botão "UPLOAD".
O mixamo.com disponibiliza um sistema de auto rigger de qualidade, seu único trabalho é demarcar os anéis nos locais certos para que o algoritmo faça a detecção de cada parte do corpo do seu personagem:



Na aba "Animations" você vai encontrar as mais variadas animações para seu jogo:



Para selecionar uma animação e visualizá-la no personagem desejado, bastar clicar sobre a mesma e vê-la fluir (no canto direito da tela):

Clique aqui para ver!

Veja que na tela da animação você pode gerenciar a visão da câmera, bem como a rotação, aproximação, movimentação e etc:


E também ajustar parâmetros de animação, como intensidade, velocidade de execução, espaçamento entre pontos, postura do personagem e etc:


*Marque a opção "In place" se não quiser que o personagem de fato se movimente pelo jogo, apenas reproduza a animação.

É possível filtrar a pesquisa por animações através da barra de buscas localizada no canto superior esquerdo da tela. Você pode buscar por uma animação específica bastando digitar a palavra-chave (ex: "Walking") ou pode filtrar a pesquisa através das tags do site:


Para nosso tutorial, vamos fazer com que o personagem tenha a animação andando, parado e dando um combo de ataques (chutes e socos), então para seguir o tutorial, pesquise por animações que correspondem a estes requisitos e baixe-as.
Para baixar, clique sobre o botão "Download" e essa tela aparecerá:



Mude a opção "Format"para ".FBX for Unity" e baixe a primeira animação com a opção "Skin" em "With Skin" e as demais com a opção "Without Skin", pois com a Skin iremos baixar o modelo 3D do personagem e com a opção "Without skin" iremos baixar apenas as animações (movimentos e parâmetros).




Trabalhando com a Unity:
Uma vez com a engine Unity aberta, crie uma pasta no seu jogo chamada "Characters" e arraste todas as animações baixadas para dentro desta pasta:



Agora coloque na cena a animação que possui Skin.
Veja no inspector que este objeto já possui um componente incluso, justamente o Animator Controller, porém não existe um controlador atachado a este componente, por enquanto:


Para acabar com este problema, vá até a pasta "Characters" e com o lado direito do mouse vá em "Create" >> "Animator Controller", e coloque o nome que desejar, dessa forma você estará criando um controlador para o componente do seu personagem. Ao clicar duas vezes neste objeto, você abrirá esta janela:



Através desta janela você poderá controlar o fluxo de animações do personagem que possui este componente como controller.
Arraste a animação do personagem parado para esta janela e veja o que ocorre:



Agora você possui uma transição de entrada de cena para a animação do zombie parado!
Essa setinha laranja que conecta os dois estados se chama "transition" (transição) e será através dela que iremos controlar quais animações deverão ser executadas e em quais momentos isso deve ocorrer.
Porém, primeiramente vamos testar o que ocorre quando você referencia este controller criado no "Animator Controller" do personagem através do inspector:



Aperte play e perceba que a animação até é executada, mas quando chega ao final ela para. Concorda que para esse tipo de animação, o ideal seria a animação continuar num loop infinito? Pois bem, para colocar uma animação em loop, basta clicar sobre ela na janela de "Assets" e através do inspector na janela "Animations", marque a opção "Loop time":



Aplique a alteração e perceba que agora a animação realmente entra num loop, terminando e recomeçando.
Se você colocar o layout da interface em 2 por 3 e der play no jogo com a janela do Animator aberta e com o personagem selecionado, você vai poder visualizar a animação sendo executada em runtime:

Clique aqui para ver!

Para criar o restante do fluxo, arraste as outras animações para a janela do Animator Controller:



*Coloque o loop time na animação "Walking" também"!

Agora é hora de criar as transições!
Na animação "Idle" clique com o lado direito do mouse e vá à opção "Make Transition" e conecte a setinha com a animação "Walk", também faça o inverso e crie uma transição de "Walk" para "Idle":



Dessa forma você terá transições da animação "parado" para "andando" e de "andando" para "parado":



Dê play no jogo e veja que após a animação do personagem parado acabar, se inicia a animação dele andando, porém, no jogo não é isso que queremos! Apenas deve-se realizar a animação do personagem andando quando ele de fato andar, não assim em sequência como está.
Para gerenciar as transições de forma correta nós iremos utilizar um artifício da Unity e do Animator Controller que são os parâmetros:



Existem 4 tipos de parâmetros: Bool, Trigger e os numéricos (int e float). Eles são responsáveis por controlar as transições nas animações.
Clique no símbolo de mais (+) para adicionar um novo parâmetro. Ele será do tipo "bool" e terá o nome "estaParado":



Como é de se imaginar, este parâmetro irá gerenciar se a animação do personagem parado deve ser executada ou não.
Agora crie mais outros dois parâmetros também do tipo bool com os nomes "estaAndando" e "estaAtacando":



Vamos então condicionar a transição "parado >> "andando" clicando na transição referida.
Através do inspector procure pela propriedade "Conditions" e selecione o parâmetro "estaAndando":



Dessa forma iremos controlar o momento em que a animação do personagem andando deverá ser executada, ou seja, apenas quando o parâmetro "estaAndando" estiver verdadeiro. Controle este, inclusive, que faremos via código.
Agora na transição "andando" >> "parado" faça o mesmo, só que desta vez o parâmetro é "estaParado":



Faça agora as transições de "parado" para "atacando", sendo o parâmetro condicional "estaAtacando" e mais uma transição de "atacando" para "parado", tendo como parâmetro "estaParado".
Depois, faça com que as animações de ataque sejam exibidas em sequência, criando transições entre elas, bastando que o parâmetro "estaAtacando" seja o condicional para a reprodução dessas animações. Também faça com que todas as animações de ataque tenham transições para ''parado'' com o parâmetro "estaParado" em verdadeiro. Para que as animações de combate voltem a se repetir caso o player continue atacando, faça uma transição da última animação de ataque para a primeira, com o parâmetro "estaAtacando" em verdadeiro.
No final, você terá um fluxo como este:



Dê play e veja que apesar de termos o fluxo completo criado, o personagem só executa sua animação parado. Isso ocorre porque devemos gerenciar os estados dos parâmetros dentro do controller, e faremos isto através de código:

Em C#
Código: [Selecionar]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnimationManager : MonoBehaviour {
Animator anim;

void Start () {
anim = GetComponent ();
}

void Update () {
var estaMovendo = Input.GetAxis ("Vertical");
if (estaMovendo != 0) {
anim.SetBool ("estaAndando", true);
anim.SetBool ("estaParado", false);
} else {
anim.SetBool ("estaAndando", false);
anim.SetBool ("estaParado", true);
}

if (Input.GetButtonDown ("Fire1")) {

anim.SetBool ("estaAtacando", true);
anim.SetBool ("estaParado", false);

} else {

anim.SetBool ("estaAtacando", false);
}
}
}

Em JavaScript
Código: [Selecionar]
#pragma strict

public class AnimationManager extends MonoBehaviour{

var anim: Animator;

function Start(){

anim = gameObject.GetComponent("Animator") as Animator;
}

function Update () {

var estaMovimentando: float = Input.GetAxis("Vertical");
      if (estaMovimentando != 0){
             anim.SetBool("estaAndando", true);
             anim.SetBool("estaParado", false);
} else {
       anim.SetBool("estaAndando", false);
       anim.SetBool("estaParado", true);
}

if (Input.GetButton("Fire1")){
           anim.SetBool("estaAtacando", true);
           anim.SetBool("estaParado", false);
} else {
      anim.SetBool("estaAtacando", false);
}

}
}


Perceba que na linha "var estaMovendo = Input.GetAxis ("Vertical");" não estamos fazendo com que o personagem de fato se movimente (ande), apenas estamos armazenando uma validação se o jogador está pressionando as teclas de movimento pela vertical (baixo e cima OU s e w).
Também estamos referenciando através do objeto "anim" o componente "Animator" para que possamos ter acesso aos seus parâmetros através do método "SetBool", que pede como argumento o nome do parâmetro e o estado em que ele deve ficar, no caso aqui, true ou false.
Então o código basicamente checa se o jogador está pressionando os botões dos eixos verticais, caso sim, ele faz com que o parâmetro "estaAndando" fique true e "estaParado" fique false, e se ele soltar desses botões, o personagem ficará parado e o parâmetro "estaParado" fica true, enquanto "estaAndando" fica false.
Para os ataques, basta verificar se o jogador está pressionando o botão de ataque (lado esquerdo do mouse), caso sim, o parâmetro "estaAtacando" fica true e "estaParado" fica false (para não acontecer conflitos) e quando soltar esse botão, "estaAtacando" ficará false. Algo bem lógico, né? Por fim, adicione este script ao personagem.

Dê play e teste o jogo: Perceba que mesmo pressionando os botões corretos a animação demora a acontecer, só depois que ela termina, a próxima inicia. Como arrumar isso?
Nas transições "parado >> andando", "andando >> parado" e "parado >> atacando" através do inspector, desmarque a opção "Has exit time" que faz com que a próxima animação só seja executada se a anterior tiver terminado:



Desmarcando essa propriedade, independente do frame da animação corrente, ela será interrompida se o parâmetro for satisfeito.
Agora teste novamente o jogo e veja que agora está tudo funcionando corretamente:



Finalização:
E é isso pessoal, este tutorial foi mais focado na importação de animações para engine através do mixamo.com e divulgação do site, em breve trarei outros tutoriais mais específicos da Unity, se gostarem deste!
Até mais.

Comentários

  1. Muito bom o Tutorial, me ajudou muito, não conhecia o mixamo vai me ajudar muito

    ResponderExcluir

Postar um comentário