Tutorial Unity Rewired

Caio Felipe Giasson
12 min readOct 1, 2019

--

Olá! Esse tutorial tem como objetivo apresentar o pacote Rewired e dar alguns exemplos simples de uso, ou seja, um overview rápido sobre a ferramenta.

O Rewired é um pacote que tem por objetivo simplificar o gerenciamento de inputs na Unity. Com ele fica mais simples você implementar algumas coisas que, em outras ocasiões, teria que colocar muitas linhas de código ou até mesmo se aprofundar em uma análise que não é seu foco principal.

Assim, em vez de patinar gastando várias horas pra fazer um controle legal, single ou multiplayer, com customização de sensibilidade e outras coisas, você gasta alguns minutos e usa o resto do tempo pra trabalhar nas partes únicas do seu jogo. Pra quê reinventar a roda, não é mesmo?

Mas antes de pularmos de ponta no Rewired eu vou implementar uma movimentação básica em Unity, usando física e Input nativo. Depois a gente compara isso com o Rewired.

Implementando controles tradicionais, usando física

Primeiro eu criei um projeto em branco e adicionei um terreno e um cubo
O cubo está "cortado" pelo chão, então vou subir ele um pouco, puxando o eixo verde para cima, até eu enxergar a sombra afastada do cubo.
Não precisa ficar colado com o chão. No próximo passo vamos selecionar o Cubo e pelo Inspector vamos clicar em Add Component e na busca colocar RigidBody. Assim, quando dermos play o cubo vai "cair", mas como diziam os antigos: Do chão não passa.
Para esse tutorial a única alteração que eu sugiro é colocar um arrasto de 1, para evitar que o nosso cubo vá parar em Nárnia.
É importante que a câmera esteja virada para o lugar certo, então eu selecionei a câmera, cliquei em GameObject no menu superior, e fui em Align With View. Assim a câmera se posiciona e alinha conforme a minha visualização da cena.
Agora vamos criar um novo C# Script, com o nome Controle
A seguir eu seleciono o cubo e vou em Add Component, busco o script que eu acabei de criar e adiciono.

Finalmente vamos ao script. Basta dar duplo-clique sobre ele, na caixa Project e o editor já vai abrir. Vou deixar o código em um print e também em uma caixa do medium, pra poder copiar/colar se necessário.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Controle : MonoBehaviour {

// AQUI TEMOS OS PARÂMETROS QUE VÃO GERENCIAR O MOVIMENTO
float velocidade = 30, forcaPulo = 600;

// AQUI É SÓ UM ATRIBUTO DO TIPO RIGIDBODY, QUE COMEÇA VAZIO
Rigidbody rb;

void Start(){
// AQUI ESTAMOS VINCULANDO AQUELE ATRIBUTO ÀQUELE COMPONENTE
// QUE ADICIONAMOS AO CUBO PELO INSPECTOR
rb = GetComponent<Rigidbody>();
}

void Update(){

// COLETANDO OS INPUTS DE UM CONTROLE ANALÓGICO
float movimentoX = Input.GetAxis(“Horizontal”);
float movimentoZ = Input.GetAxis(“Vertical”);

// CRIANDO UM VETOR QUE TEM A DIREÇÃO DO MOVIMENTO
Vector3 direcao = new Vector3( movimentoX, 0, movimentoZ );

// AGORA APLICAMOS UMA FORÇA NESSA DIREÇÃO,
// MULTIPLICANDO PELA VELOCIDADE
rb.AddForce( velocidade * direcao );

// E QUANDO O USUÁRIO APERTAR “F” VAMOS FAZER O CUBO PULAR
// MOVIMENTO SÓ USA EIXOS X E Z, E PULO SÓ USA EIXO Y
// ASSIM UM NÃO INFLUENCIA NO OUTRO
if ( Input.GetKeyDown(KeyCode.F)){
rb.AddForce(0, forcaPulo, 0);
}
}
}
Testando o movimento clássico

Agora sim vem o Rewired

Primeiro é necessário instalar o pacote doRewired no projeto.

Primeiro passo é clicar e arrastar o Rewired.unitypackage direto do navegador de arquivos para a Unity
Ele vai perguntar o que você quer importar. Por enquanto vamos importar tudo, e quando tiver mais domínio sobre o que é cada coisa você pode otimizar isso importando somente o necessário. Pode clicar em Import no canto inferior direito

Durante a instalação o Rewired vai perguntar várias coisas. De modo geral, você precisa apenas avançar na instalação. No meu computador a sequência foi:
- Installing Rewired > Proceed
-
Installing Rewired: Input Manager > Add Settings
- Control Mapper > Install
-
Touch Controls > Install
-
Installing Rewired: Documentation > Skip
-
Installing Rewired > Done
Sim
, eu pulei a documentação por que ela fica disponível em:
https://guavaman.com/projects/rewired/docs/Documentation.html

Depois disso a Unity acrescenta um novo item de menu dentro de Window, através do qual nós podemos adicionar o Rewired à cena, clicando na opção realçada no print acima.
Depois disso aparece o Rewired Input Manager na caixa Hierarchy, e selecionando ele é possível ver um botão Launch Rewired Editor na caixa do Inspector. É nesse editor que vamos customizar os inputs.
Esse é o Editor do Rewired. Aqui toda a customização é feita, de modo que o esforço em código fica o mínimo necessário, independente do tipo de input que você pretende utilizar.

A lógica do Rewired é um pouco diferente de implementar controles clássicos na Unity. Para fazer controles clássicos você atua lendo diretamente os Inputs, mas com isso você obtém os dados "crus", ou raw direto da origem (joysticks, teclado, mouse, etc). Assim, qualquer tratamento ou customização precisam ser feitos em código. O Rewired transpõe esse conceito para Actions, então você customiza as Actions, mapeia elas em diferentes dispositivos de entrada, e coloca o seu código para observar quando essa Action foi executada, e não quando determinado botão foi apertado. Assim toda a customização de sensibilidade, repetição, escala, etc. é feita no editor do Rewired e o código fica menor e mais legível.

A primeira implementação do tutorial vai ser trocar os inputs anteriores por inputs normais do Rewired via teclado.

Primeiro você precisa criar um jogador, então selecione o botão Player no menu do editor e então New. Vai surgir um Player0 na lista de jogadores. Selecionando ele podemos conferir que ele tem o id 0. Esse id vai ser importante em um passo futuro.
A seguir vamos criar as Actions, selecionando o botão Action no menu do editor, e New para cada action que vamos implementar.

Há dois tipos de action: Button e Axis.
Button é quando a action é chamada por um único botão, ou seja, por uma informação binária: apertado ou não apertado. Serve para clique do mouse, por exemplo, botões do teclado, ou os botões normais de um joystick padrão.
Axis é, como os Input axis da Unity, um controle analógico, ou seja, que em vez de um valor discreto, possui um valor contínuo dentro de um certo intervalo. Normalmente esse valor contínuo vai de -1 a 1. Por exemplo, o eixo vertical de um controle analógico vai de -1 (posição para baixo) até 1 (posição para cima).

O pulo vai ser um input do tipo Button. Não há muita customização necessária nesse caso.
O movimento frontal é equivalente ao que a unity trata no Input axis vertical. Eu evitei chamar de vertical por que pra mim o vertical é o eixo Y, que é a direção para onde o pulo ocorre. Note no print que eu chamei o movimento positivo de Frente e o negativo de Trás. Essa parte vai ser útil para a hora que formos mapear as Actions para diferentes tipos de entrada.
De forma análoga, o movimento lateral também vai ser um eixo, e convencionando de forma similar ao plano cartesiano, o sentido positivo fica para a direita.

Agora temos as nossas Actions e o nosso Player. Precisamos mapear essas actions para alguma forma de entrada. O primeiro teste vai ser usando o teclado, onde fazemos o mapeamento tecla por tecla.

Clique no botão Keyboard Maps no menu do editor e a seguir Create Map.
O mapa é sempre criado vazio então temos que popular com os elementos desejados, clicando em New. Depois disso o editor nos mostra a última coluna para customizarmos o elemento. A primeira caixa é Key, ela serve para selecionarmos qual a tecla que vai ser vinculada a esse elemento. É possível selecionar de duas formas: rolando a caixa (que está com A, B, C, D, E, F… no print) ou clicando no botão Poll for Key Press. Quando clicamos nesse botão o editor vai "escutar" o seu teclado, então a próxima tecla que você apertar no teclado será atribuída a esse elemento direto, sem precisar encontrar ela na lista.
Esse primeiro elemento foi o mais simples: O botão de pulo. Eu cliquei em Poll for Key Press e então apertei F, depois na caixa de Action mais abaixo eu selecionei a ação de Pulo. Agora sempre que a tecla F for apertada ele vai chamar o evento de Pulo.
A próxima tecla escolhida foi a tecla A. Na caixa Action eu vinculei ela à ação de Movimento Lateral. Note que foi necessário selecionar Negative no campo Axis Contribution, para que essa tecla fique exclusivamente vinculada ao movimento da esquerda. Dessa forma o Rewired vai entender que apertando ela é equivalente a mover o controle analógico para a esquerda.
De forma análoga, a tecla D precisa ser vinculada ao movimento lateral, com Axis Contribution positivo.

As outras teclas, W e D, devem ser vinculadas ao movimento Frontal.
W vai ter Axis Contribution positivo e S vai ter Axis Contribution negativo.

Esse é o resultado final. Apenas olhando para a lista de elementos já dá pra ver que W é vinculado com a ação de mover para a frente, S para trás, A para a esquerda, D para a direita e F para pular.

Depois de criar o Player, cadastrar as Actions e mapea-las para o teclado é necessário vincular esse mapa ao player que nós criamos. Para isso basta voltar à tela de Players do Editor do Rewired.

Clicando no botão Players no menu do editor, selecionando o Player0 e clicando no botão Keyboard Maps vemos que inicialmente não há mapas vinculados. Então é só clicar no botão Add Keyboard Map que ele já será vinculado automaticamente.

Nessa etapa o setup básico do nosso controle está feito.
Pode parecer um pouco longo mas de fato executar isso pela segunda vez leva menos de 1 minuto!!!!

Agora podemos fechar o editor do Rewired (Ele já salvou a customização) e voltar para o código.
No print do código estão destacadas as alterações, com comentários.

Esse é o código já utilizando o Rewired. Ao dar play no projeto a movimentação fica bem semelhante ao que estava antes, porém, agora temos um potencial de customização enorme. Na sequência vamos brincar um pouco com isso.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Rewired;

public class Controle : MonoBehaviour {

// AQUI TEMOS OS PARÂMETROS QUE VÃO GERENCIAR O MOVIMENTO
float velocidade = 30, forcaPulo = 600;

// AQUI É SÓ UM ATRIBUTO DO TIPO RIGIDBODY, QUE COMEÇA VAZIO
Rigidbody rb;

// A ESSE ATRIBUTO VAMOS VINCULAR O NOSSO JOGADOR
Player jogador;

void Start() {
// AQUI ESTAMOS VINCULANDO AQUELE ATRIBUTO ÀQUELE COMPONENTE
// QUE ADICIONAMOS AO CUBO PELO INSPECTOR
rb = GetComponent<Rigidbody>();

// AQUI ESTAMOS VINCULANDO O PLAYER0 CRIADO NO EDITOR
jogador = ReInput.players.GetPlayer(0);
}

void Update() {

// COLETANDO OS INPUTS DE UM CONTROLE ANALÓGICO
//float movimentoX = Input.GetAxis(“Horizontal”);
//float movimentoZ = Input.GetAxis(“Vertical”);

float movimentoX = jogador.GetAxis(“MovimentoFrontal”);
float movimentoZ = jogador.GetAxis(“MovimentoLateral”);

// CRIANDO UM VETOR QUE TEM A DIREÇÃO DO MOVIMENTO
Vector3 direcao = new Vector3(movimentoX, 0, movimentoZ);

// AGORA APLICAMOS UMA FORÇA NESSA DIREÇÃO,
// MULTIPLICANDO PELA VELOCIDADE
rb.AddForce(velocidade * direcao);

// E QUANDO O USUÁRIO APERTAR “F” VAMOS FAZER O CUBO PULAR
// MOVIMENTO SÓ USA EIXOS X E Z, E PULO SÓ USA EIXO Y
// ASSIM UM NÃO INFLUENCIA NO OUTRO
if ( jogador.GetButtonDown(“Pulo”) ) {
//if (Input.GetKeyDown(KeyCode.F)) {
rb.AddForce(0, forcaPulo, 0);
}
}
}

Você pode estar se perguntando:
"Mas eu continuo usando um GetAxis, só em vez de fazer isso no Input estou fazendo no jogador."

Sim, exato. Mas há uma diferença conceitual enorme, e que para controles extremamente básicos (como o exemplo usado) fica muito parecido, mas para controles mais complexos.
Todas as vezes em que atuamos sobre o RigidBody no código acima isso acontece quando uma determinada ação é chamada, e não quando um determinado botão é apertado.

OK, aqui termina a "parte 1", que é implementar o movimento mais básico usando o Rewired.
Daqui por diante vamos experimentar algumas das funções seguintes do Rewired para ficar claro o potencial de customização da ferramenta, com o mínimo de edição de código.

Primeiro passo vamos voltar para o editor, clicando no Rewired Input Manager que há na Hierarchy e então em Launch Rewired Editor (Como fizemos antes).

Tela inicial do Editor do Rewired

No print acima podemos ver já algumas das opções de customização:
Update Loop serve para escolhermos em qual dos métodos MonoBehaviour vai ter acesso aos inputs. Claro, se estiverem disponíveis em somente um deles o desempenho tende a ser ligeiramente maior.
Platform Settings serve para customizar o comportamento básico dos inputs em cada plataforma, como por exemplo, usar somente teclado se for Windows/Linux/OSX e somente input nativo se for PS4/Xbox One/WiiU.
Joystick Auto-Assignment é um dos mais interessantes: É aqui que o Rewired regula o comportamento do jogo vinculando um novo joystick automaticamente ao próximo player no instante em que o joystick é reconhecido. Assim quando você cadastra vários players e aplica o mesmo mapa a eles, não é necessário customizar qual botão faz cada função, e basta você ter um prefab para cada ID de player, por exemplo.

Agora vamos brincar com mouse input. Vamos fazer o nosso cubo seguir o mouse pela tela.

Primeiro acessar a tela Mouse Maps pelo menu do editor, e então clicar em Create Map. Depois disso é muito semelhante ao mapa de teclado: ao adicionar um elemento em New o editor vai mostrar as opções no lado direito.
Aqui eu implementei o pulo quando for clicado no botão esquerdo do mouse.
Agora fiz os outros dois eixos. Como o mouse já possui dois eixos implementados (Mouse Vertical e Mouse Horizontal) eu só precisei vincular esses elementos às ações que criamos no começo do tutorial.
Depois disso ainda é necessário ir no menu Players, selecionar nosso conhecido Player0, entrar no Mouse Maps para esse jogador e clicar no botão Add Mouse Map. O mapeamento que criamos no passo anterior já foi vinculado automaticamente.

Agora podemos fechar o editor do Rewired e dar play no projeto

Note que a sensibilidade ficou alta demais, então precisamos aliviar um pouco esse comportamento.

Então podemos voltar ao Editor do Rewired e, como a palavra já sugere, ir para o menu Input Behaviours

Nesse caso foi bem tranquilo, bastou editar o Mouse XY Axis Mode para Digital Axis e a sensibilidade já ficou tranquila. Porém, poderia ser usado um ajuste fino no campo Mouse Other Axis Sensitivity. Também é possível pegar somente o "delta" da posição do mouse em relação ao centro da tela, ou a velocidade da tela (essas opções aparecem dentro do item Mouse XY Axis Mode). Recomendo que você teste cada opção para ver como se comporta.
A sensibilidade já ficou melhor… porém, eu reajustei a posição da tela em algum momento, e com isso o movimento vertical ficou OK mas o horizontal ficou invertido.

Para corrigir isso basta acessar novamente o editor do Rewired e procurar onde está o movimento horizontal do mouse, para inverter o sentido.

Basta clicar na checkbox Invert Axis, e pronto, o movimento está invertido. Agora é só fechar o editor e rodar novamente pra testar.
Bem melhor!

Detalhe importante: Desde que implementamos o código para o Rewired não foi necessário mexer no código. Só adicionamos um novo controle (no caso, o mouse) ao nosso player. Repare que o teclado continua funcionando normalmente, e que as customizações que fizemos afetaram somente o movimento pelo mouse.

O Rewired tem um potencial incrível, eu recomendo fortemente que cada um explore um pouco dele por que economiza vários passos e muitas linhas de código. Abaixo vou comentar um pouco sobre outras customizações na tela de Input Behaviours.

Repare que há uma lista de Input Behaviours do lado esquerdo. Podemos ter um perfil de comportamento diferente para cada item dessa lista, e alternar dinamicamente, se necessário, usando inclusive isso como elemento de gameplay, caso seja interessante.

Alguns dos itens mais usados na customização, nessa tela, são:
Joystick Axis Sensitivity: Aqui você altera a sensibilidade dos controles analógicos. Isso vai afetar os joysticks que estejam mapeados para o determinado player, e é um atributo interessante para, por exemplo, aplicar um efeito de "lentidão" ou "dificuldade de reação" ao personagem do jogo.
Digital Axis Simulation: Essa checkbox serve para indicar que quando estiver usando controles digitais você possa simular o comportamento analógico. Por exemplo, usando WASD, se vc está indo pra frente (W) e então aperta para trás (S) o input não vai direto de 1 para -1 e sim percorre um caminho "suave" entre os dois extremos.
Digital Axis Snap: Quando você atua sobre uma alavanca analógica (um manche ou um stick de um controle de XBox / Playstation, por exemplo), ao soltar a alavanca ela tende para a posição central. Essa opção simula isso quando você estiver usando botões digitais para emular um analógico.
Button Double Press Speed: Determina o tempo entre dois clicks para que o Rewired entenda que ocorreu um evento de "double-click". Esses eventos estão disponíveis no código ao chamar player e apertar o ponto ".", na caixa de autocompletar preencha Double e note que o evento já aparece na lista de eventos disponíveis.
Button Short Press Time: Esse parâmetro tem duas "etapas", o Short Press Time e o Short Press Expires In. Ele basicamente começa a contagem de um short press quando o jogador inicia uma Action, e retorna true enquanto estiver no Short Press Time. Quando essa contagem de tempo passa do valor do Expires In ele passa a retornar false. Isso serve para, por exemplo, implementar aquela clássica mecânica de ter um pulo mais curto quando aperta o botão bem rápido, e um pulo normal quando aperta o botão por mais tempo.

Enfim, cada customização dessas já remete a uma mecânica básica conhecida, e combinações entre elas podem ser usadas para mecânicas novas ou experimentais.

Os outros Input Behaviours que eu não comentei caso a caso podem ser consultados pela tooltip que aparece quando você deixa o mouse parado sobre o nome do campo, conforme exemplo abaixo:

Aqui o ponteiro do mouse foi deixado sobre o Button Long Press Time, e a tooltip explicando o que faz esse parâmetro apareceu após cerca de um segundo.

Enfim, para finalizar o tutorial, vamos implementar aquela mecânica do pulo rápido e do pulo longo , que utiliza o evento Button Short Press.

A parametrização no editor do Rewired foi bem simples: O short press começa em 0 e acaba em 0.3 segundos, ou seja, se o jogador apertar e soltar o botão em menos de 300 milissegundos o controle vai entender que ocorreu um evento ShortPress.

Importante ressaltar que isso acontece na camada de comportamento do controle. Portanto, afeta todos os controles (no caso do projeto atual afeta o mouse e o teclado). Na prática ele está atuando em qual evento está ou não sendo chamado para cada action.

Essa customização envolve alterações suaves no código por que nesse caso estamos atuando no evento do pulo, e não apenas na customização do controle. Mas a alteração é muito singela, segue print e código abaixo. Detalhe: apaguei os comentários do código por que todos eles estão nos códigos anteriores, o foco é o trecho específico do "pulo curto".

Primeiro verificamos se ocorreu o evento Short Press. Se ele tiver ocorrido então chamamos um pulo com 1/3 da força original. Caso ele não tenha ocorrido, verificamos se ocorreu um pulo normal. Em caso positivo, chamamos um pulo idêntico ao que havia antes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Rewired;

public class Controle : MonoBehaviour {

float velocidade = 30, forcaPulo = 600;

Rigidbody rb;
Player jogador;

void Start() {
rb = GetComponent<Rigidbody>();
jogador = ReInput.players.GetPlayer(0);
}

void Update() {
float movimentoX = jogador.GetAxis(“MovimentoFrontal”);
float movimentoZ = jogador.GetAxis(“MovimentoLateral”);

Vector3 direcao = new Vector3(movimentoX, 0, movimentoZ);
rb.AddForce(velocidade * direcao);

// PRIMEIRO IDENTIFICAMOS SE OCORREU UM SHORT PRESS
// SHORT PRESS UP INDICA O INSTANTE EM QUE SOLTOU O BOTÃO
if (jogador.GetButtonShortPressUp(“Pulo”)) {
// PULO COM 1/3 DA FORÇA
rb.AddForce(new Vector3(0, forcaPulo / 3, 0));
}
else
// O ELSE INDICA QUE CASO NÃO TENHA SIDO UM SHORT PRESS,
// AINDA PODE TER SIDO UM PRESS NORMAL
if (jogador.GetButtonUp(“Pulo”)) {
// PULO NORMAL
rb.AddForce(new Vector3(0, forcaPulo, 0));
}
}
}

É importante destacar que em nenhum momento precisamos chamar uma tecla específica do teclado, um botão específico do mouse ou um botão específico do joystick. Apenas estamos verificando se um determinado evento aconteceu com uma determinada Action.

No caso acima primeiro verificamos se o evento GetButtonShortPressUp ocorreu com a Action Pulo. Caso ele não tenha ocorrido, daí verificamos se um outro evento ocorreu: GetButtonUp, na mesma Action Pulo.

Dessa forma o Rewired entende que cada player vai ter um joystick diferente ou um botão diferente para chamar aquela action, mas a lógica continua a mesma, por que a chamada é feita pela Action e não pelo Input, como no exemplo clássico (que foi a primeiríssima implementação desse tutorial, antes de adicionar o Rewired no projeto).

Enfim, esse foi o "breve" tutorial sobre o Rewired. Nesse tutorial não abordamos sequer 5% do potencial da ferramenta, então a minha recomendação para vocês é: Explorem a ferramenta. Tentem adicionar ela a um projeto vazio e experimentar o comportamento, fazer customizações, analisar o resultado e brincar bastante.

Ninguém conhece o seu projeto melhor do que você mesmo. Dedique seu tempo para fazer as coisas únicas do seu jogo. Não perca tempo implementando algo que outras pessoas já implementaram e que talvez não sejam o seu principal diferencial.

A quem chegou aqui, muito obrigado! TCHAU, FUI!!!!

--

--