Menu

Tutorial de Unity 2D – Extra – Programação

E iniciando hoje um post extra do nosso tutorial de Unity! Bom, como já havia comentado com vocês que haviam me pedido um tutorial focado em programação no Unity, trouxe esse post com essa finalidade!

Se vocês já iniciaram o tutorial, significa que já estão bem encaminhados, o que é bom sinal, pois já tiveram contato com a parte de programação de um jogo. Então vamos ao que interessa: Por que programar?

A programação do jogo é a parte responsável pela jogabilidade do seu jogo. Ou seja, será ele que irá dizer que quando você apertar um botão X, ele irá executar a ação Y. Também será ele responsável por fazer o controle de quando uma animação de um personagem será ativada ou controlar o HP do personagem. Sendo assim, a programação é onde irá dar vida a quase tudo dentro do jogo.

“Mas eu nunca programei antes, não entendo nada daquelas linhas!”, é justamente por isso que estou fazendo esse tutorial. Não se preocupem que aqui não irei trazer um tutorial pesado de programação, mas apenas o básico para que vocês consigam criar seus jogos em Unity.

Se vocês quiserem, podem optar por se aprofundar no conhecimento de programação pegando algum curso de algoritmo (script) ou linguagem de programação (preferencialmente C#, para usar no Unity), mas mesmo que você faça um curso desse, você ainda sim irá precisar aprender a programar no Unity, pois algumas coisas são diferentes e existem conteúdos já prontos para serem usados no Unity.

Quando eu for apresentar conteúdos de programação, irei dá uma visão de programador e depois puxarei para o Unity. O motivo para eu apresentar um pouco dessa visão de programador, é porque acho interessante vocês saberem o básico para conseguir trabalhar em equipe com programadores, tirar dúvida e saber se expressar de forma correta. E para quem gostar de programação, poderá já ter uma visão melhor do que o espera!

Script

A primeira coisa que vocês precisam entender é o que é o script. O script nada mais é do que o seu roteiro. Vamos imaginar numa peça de teatro, cada participante dessa peça tem um script, que ele irá realizar conforme esta no papel, correto? Falas e ações. E esse script é executado sempre de cima para baixo. Ou seja, se na minha peça meu script é:

*Entra no palco*
Falar “Bom dia Pessoal”
*Se a plateia não responder, devo falar de novo “Bom dia Pessoal”*
*Senão devo agradecer pelo Bom dia*

Isso significa que irei executar esse script de cima para baixo respeitando as regras. Convertendo isso para C#, iriamos ver:

entrarPalco();
Console.WriteLine(“Bom dia Pessoal!”);
If (getResposta() == true)
	Console.WriteLine(“Bom dia Pessoal!”);
else 
agradecer();

Ou seja, acabamos de criar um simples script para um personagem de uma peça, que poderia ser um NPC de um jogo. Imagine agora que para cada personagem da peça, tivéssemos um script dizendo o que ele VAI fazer, o que ele PODE fazer e QUANDO ele deve fazer. É basicamente isso que faremos com nossos scripts de C#. Vamos criar o “roteiro” para os objetos, pessoas e recursos do nosso jogo.

Para criar um Script, podemos fazer de duas formas. A primeira é clicando com o botão direito em um canto vazio na aba Project, indo na opção Create e escolhendo a opção C# Script.

A segunda opção é indo direto no nosso objeto que iremos atribuir o script na aba Hierarchy e depois na Aba Inspector escolhermos Add Component >> New Script.

Já fizemos bastante isso nos nossos tutoriais não é mesmo? Se você quiser atribuir um Script já existente, basta ao invés de escolher a opção New Script, ir à opção acima, Scripts, e escolher o script que você deseja.

Diante disso, é bom começarmos a entender a estrutura do nosso script. Toda peça de teatro que for organizada terá um modelo de script, onde o script informará os atos, nomes e tudo mais, certo? Então no nosso script também vamos precisar seguir um modelo, que será de acordo com uma linguagem de programação, no nosso caso o C#.

O modelo do nosso script é representado por:

Onde:

Linha 1 e 2 = estamos dizendo que no nosso roteiro (script) irá depender desses outros.

Linha 4 = dizemos que nosso script, que é uma class, possui o nome “NomeScript” e herda características em comuns de MonoBehaviour. Vamos assim imaginar que eu o palhaço do Circo vou ter conteúdos em comuns com o script do Mágico do Circo. Logo eu e ele herdaremos uma class em comum, que no nosso script será o MonoBheaviour.

Linha 6 = Estamos chamados um método Start, padrão do MonoBehaviour, onde informamos que assim que começamos a executar nosso script, iremos realizar a ação dentro do método Start. Um exemplo para músicos seria arrumar os instrumentos musicas.

Linha 9 = Já aqui, estamos dizendo que enquanto estiver executando o meu papel, irei realizar as atividades dentro do Update. Aqui seguindo o mesmo exemplo dos músicos, seria enquanto eu estiver realizando meu papel (Estiver no palco, que seria a nossa scene no Unity), irei tocar música.

Ainda existem outros métodos que são herdados do MonoBehaviour que iremos discutir mais na frente.

Class e Herança

Bom eu falei agora a pouco de Classe e Métodos, mas o que são isso? Na programação, usamos algo chamado Orientação a Objeto, onde pegamos características e atividades em comuns de um objeto e as definimos em um roteiro. Pensando assim podemos dizer que num show musical podemos criar Classes de características em comuns e atribuir para os nossos objetos que seriam as pessoas.

Exemplo, podemos criar uma Class chamada Artista, que vai entrar no palco e tocar. Podemos também criar outras classes chamadas Cantor, Tecladista, Guitarrista e Baixista, onde eles vão herdar características em comuns de Artistica, afinal todos são artistas e fazem coisas em comuns, porém para cada um terá uma ação em particular e instrumentos diferentes, o que podemos representar na imagem abaixo:

Curtam meu belo desenho feito no Paint

De acordo com essa imagem, estamos dizendo que todos são “Artista” e terão uma ação (Métodos de verde) em comum (EntrarNoPalco). Porém mesmo todos sendo “Artista”, ainda podem ser diferentes, como é o caso que ocorre com cantor que tem Microfone como atributo de instrumento (Atributos/variáveis de vermelho) e uma ação (método) exclusiva “Cantar”.

Desta forma acho que vocês já estão começando a ter uma visão de herança, Classes e Métodos. Porém eu comentei algo chamado atributo. Os atributos são variáveis especificas de um objeto, que serão usadas no script. No nosso exemplo eu usei o atributo instrumento.

Variáveis

Na programação existem vários tipos de variáveis. Um exemplo disso é para representar o número inteiro podemos ver variáveis do tipo: tinyint, smallint, int, bigint. Mas não se preocupem, aqui vou listar as que vocês mais vão usar para programar os seus jogos.

string – Textos. Ex: “Eu odeio programação”

int – Números inteiros. Ex: …-2, -1, 0, 1, 2…

float – Números decimal. Ex: 1.5f, 3.5f, 2.12313123f (Na matemática nós usamos a vírgula, mas na programação usamos o ponto ao invés da vírgula para indicar que o número não é um inteiro. E não usamos números fracionários como ½. Ele já entende que isso é igual a 0.5). O f serve para indicar que é do tipo float.

bool – valores booleanos ou Verdadeiro e Falso. Para quem nunca mexeu com programação, provavelmente não sabe o quanto isso é utilizado, porém basicamente tudo na programação é 1 ou 0 (Verdadeiro ou falso). Ex: true e false

GameObject – São os objetos que você cria no Unity. Ex: O Player.

Transform – Pega os atributos transform (Escala, posição, rotação e componentes) do objeto.

Essas variáveis podem ser públicas (public) ou privadas (private). Para quem for estudar programação, pode ainda ver protected e internal, mas aqui no Unity só usaremos essas duas. Agora saibam quando usar cada uma:

Public – Poderá setar (Termo usado para atribuir um valor) o valor inicial no Unity. Sendo assim, se você criou um script genérico que pode ser usados em vários objetos, mas quer que eles tenham atributos diferentes, deixe esse valor como público. Exemplo que eu posso dá é o dos instrumentos musicais lá em cima, se você criar um script que tenha a variável instrumento do tipo GameObject, pelo Unity você poderá dizer qual instrumento ele usará. Bastante útil para a arma que um personagem usa.

Private – São os atributos que você não deseja que seja alterado fora do script atual, o que significa que também não terá acesso pelo Unity (Quando eu falo Unity, significa que estou me referenciando ao Ambiente visual, e o MonoDevelop ao local onde criamos os códigos).

A declaração de uma variável ocorre indicando se ela é public ou private seguido do seu tipo e por ultimo o nome. Quanto ao nome, não usamos espaço, acentuação e ç. Quando o nome é composto, usamos por padrão a primeira letra da segunda palavra maiúscula. Essa pratica é chamada de Camel Case, porém nada lhe impede de criar uma variável: vAriaVel_PriVadA, porém é melhor manter um padrão universal, inclusive se você usar o Camel Case o Unity traz essa variável de forma legível na aba Inspector como pode ver na imagem abaixo (variavelPublica virou Variavel Publica):

Declarando sua variável desta forma, ela estará disponível em todo o script, mas você também pode declarar uma variável dentro de um método, só que assim ele apenas vai funcionar dentro do método.

	void Update () {
		bool exemplo = true;
	}

Métodos

Agora em relação aos métodos, precisamos aprender algumas coisas sobre eles. Os métodos como já vimos eles indicações as ações que nosso script pode fazer. Exemplo no caso da criação do personagem, podemos criar os métodos: Movimentar e Atirar.

Carlos, podemos fazer tudo em um script só? Podem, mas ficaria muito bagunçado e poderia até ficar repetido, o que é péssimo para manutenção. Pensem comigo que vocês têm um método de 30 linhas e ele é executado em dois cantos separados, isso significa que se você for escrever tudo junto isso daria 60 linhas, mas e você fizer um método poderá realizar apenas a chamada em locais diferentes. A chamada de um método no Unity ocorre da seguinte forma:

	void Start () {
metodo1 ();
		metodo2 (1);
		int booleano = metodo3 ();
		Debug.Log ("Valor " + booleano);
	}

No metodo1 temos um método que não retorna nada e não necessita de variáveis na sua declaração. Útil quando queremos que realize uma ação independente.

	void metodo1() {
		Debug.Log ("Entrou no Metodo 1");
	}

No metodo2 temos um método que não retorna valor algum e necessita de um valor de entrada. Usamos isso quando queremos que nosso método execute alguma ação em relação ao valor atribuído.

	void metodo2(int inteiro) {
		Debug.Log ("1 + " + inteiro + " = " + (1+ inteiro));
	}

E por ultimo no metodo3 temos um método que retorna um valor, para quem o chamou:

	int metodo3() {
		return 3;
	}

Repare que não estamos mais atribuindo void antes do método, mas sim o tipo de variável que ele irá retornar. Se ele não retornar nada, declaramos como void. Normalmente seus scripts serão no estilo do metodo1.

Ao executar esse script, vamos observar na aba Console lá no Unity os seguintes valores:

Onde o metodo1 irá apenas realizar a ação de informar que entrou no método 1. No metodo2, iriemos mostrar a soma de 1 + o valor passado como referência pelo metodo2. E no metodo3 iremos apenas retornar um valor inteiro que é exibido no método start().

“Ah, e se perceberam, dentro do nosso método e toda vez que criamos uma nova variável no final da linha adicionamos o “;” que indica o final do comando. No caso de métodos, usamos “{“ e “}” para indicar o inicio e o fim do método, por isso que ele não possui “;”.

Estrutura de Decisão

O uso das chaves, também é comum quando usamos algumas estruturas de decisão. Basicamente a que vocês vão usar é o condicional “if” e “else”. Então irei apresentar apenas essas, caso venhamos precisar de mais, eu posso criar mais um tutorial de programação para vocês.

As estruturas de decisão são onde tornam o nosso código dinâmico, do contrário eles sempre iriam executar sempre as mesmas ações. Para entender melhor pense assim, o meu personagem só vai atirar quando eu apertar o botão de atirar, o que pode ser entendido da seguinte forma:

	void Update () {
		if (Input.GetButton ("Fire1")) {
			atirar();
		}
	}

Obs: Fire1 = Botão Ctrl

A ideia do if, é bastante simples. SE o conteúdo dentro dos parênteses for verdadeiro, ele executa a ação. O else se o conteúdo não for verdade. Logo:

		if (1 < 2) {
			Debug.Log ("Entrou no if");
		} else {
			Debug.Log ("Entrou no else");
		}

Qual o texto que será exibido dentro do Console? Se 1 é menor que 2 é verdade, então ele entrará no if e irá ignorar o else. Se 1 não fosse menor que 2, ele entraria no else e ignoraria o if. Deixando isso mais claro:

		if (true) {
			Debug.Log ("Entrou no if");
		} else {
			Debug.Log ("Entrou no else");
		}

Resultará em “Entrou no if”.

		if (false) {
			Debug.Log ("Entrou no if");
		} else {
			Debug.Log ("Entrou no else");
		}

Resultará em “Entrou no else”.

Debug

Já entendemos algumas informações básicas para iniciar nossos scripts junto ao tutorial lá do Unity, então vamos iniciar as explicações de algumas Classes que nos ajudaram em nosso jogo (E isso você não vai aprender em curso de programação como falei, pois são classes exclusivas do Unity).
Aproveitando que já mostrei a class Debug, vamos conhecê-la melhor, pois ela será a maior aliada de quem mexe com programação.
Primeiro o que é Debug, debug é você “debugar” o seu código, ou seja, procurar onde está aquele bendito erro, ou usar recursos que te ajudem a analisar seu código. Vamos ver alguns métodos presente nele.

Log

O método Log da classe Debug, como você deve ter visto, serve para imprimir valores na aba Console lá no Unity. Sendo assim, se você quiser saber se o seu script tem algum erro ou se aquela ação está entrando no seu if, você pode simples colocar assim:

		if (Input.anyKey) {
			Debug.Log ("Algum botao foi apertado");
		}

Ao aperta algum botão você poderá observar no Unity a mensagem:

O texto deve ser escrito em aspas duplas e se quisermos exibir uma variável junto ao texto, devemos fecha a aspa do texto adicionarmos o + (Essa ação é chamada de concatenar, juntar a variável ao texto) e depois a variável.

		if (Input.anyKey) {
			Debug.Log ("O nome desse objeto eh " + gameObject.name);
		}

DrawLine

DrawLine irá criar uma linha entre dois pontos na nossa aba Scene (Aba onde iremos praticamente fazer todos os nossos testes visuais). Vocês se lembram o que fizemos com o Player e o ChaoVerificador, para que pudéssemos pular no nosso tutorial de movimentar personagem? A ideia aqui é mesma, vamos ter a posição de um objeto e de outro, e o DrawLine será responsável por criar uma linha entre os dois objetos na cor que você determinar (Senão determinar será branco). Para entender isso, vamos criar duas variáveis públicas:

	public GameObject objeto1;
	public GameObject objeto2;

E depois um método que será chamado no Update.

	void DrawLine() {
		Debug.DrawLine (objeto1.transform.position, objeto2.transform.position, Color.green);
	}

Pronto, agora é só criar dois objetos no Unity (Menu >> GameObject >> Create Empty) e dizer ao script quais são esses dois objetos (Basta arrasta-los da aba Hierachy para o Script na aba Inspector.

ClearDeveloperConsole

Se você estiver fazendo vários testes e seu Console que esteja cheio de mensagens de erros que te atrapalhem, você pode simplesmente limpa-lo usando o ClearDeveloperConsole.

	void Clear() {
		Debug.ClearDeveloperConsole ();
	}

Break

Break permite que você pause o jogo para debug, caso você deseje. Lembrando que isso também pode ser feito pelo Unity no botão ao lado do Play, terá a mesma função, porém em casos muito rápidos ou casos específicos, será melhor usar o código.

	void Break() {
		Debug.Break ();
	}

MonoBehaviour

O MonoBehaviour é a classe principal do nosso Unity, que nossos scripts herdam métodos dele. Então normal a gente conhecer alguns desses métodos não?

Invoke

Invoke irá “invocar” uma função dentro de um tempo X. Exemplo, eu quero que o meu jogo após 5 segundos de iniciado, apareça a mensagem “Olá” no Console. (Cuidado para não usar um invoke direto no Update, pois do contrário irá invocar a cada frame aquele método)

	void Start () {
		Invoke ("BoasVindas", 5f);
	}

	void BoasVindas() {
		Debug.Log ("Ola");
	}

InvokeRepeating

E se eu quiser invocar mais uma vez. Como uso de forma correta então? Simples, basta usar o InvokeRepeating, que irá chamar o método em X segundos a cada Y segundos.

InvokeRepeating ("BoasVindas", 5f, 2f);

Logo a cada 2 segundos, eu irei dizer que o método BoasVindas vai aparecer após 5 segundos. Então ele irá aparecer em:

5 segundos

7 segundos

9 segundos

...

CancelInvoke

Ok entendi, mas não quero que ele pare de repetir de chamar esse método a cada 2 segundos, como faço? Você utiliza o CancelInvoke, que irá cancelar TODOS os métodos que estão para ser invocados e repetições.

void Start () {
		//Invoke ("BoasVindas", 5f);
		InvokeRepeating ("BoasVindas", 5f, 2f);

	}

	void BoasVindas() {
		Debug.Log ("Ola");
	}
	
	void Update () {
		if (Input.anyKey) {
			CancelInvoke();
		}
	}

Start

O método Start será responsável por executar um código uma única vez e no exato momento em que o objeto for criado.

	void Start () {
		Debug.Log ("Objeto Criado");
	}

Update

O método update irá executar tudo que estiver no nosso script enquanto ele existir. É provavelmente o principal método que iremos utilizar, mas para não executar uma ação sempre, utilizaremos o if, para que ele execute a ação quando uma situação for satisfeita (Como aperta um botão).

	void Update () {
		if (Input.anyKey) {
			Debug.Log ("Voce esta apertando um botao!");
		}
	}

Destroy

Destroy é um método utilizado para destruir/excluir/deletar um objeto. Se você quiser destruir o próprio objeto você deve passar como parâmetro gameObject. E se quiser que ele seja destruído em x segundos, você passa os segundos como segundo parâmetro do método Destroy.

Destroy (objeto1);
Destroy (gameObject, 5f);

Instantiate

O Instantiate é o contrário do Destroy. Enquanto o Destroy exclui, o Instantie cria um novo Objeto na posição (Vector3 (X,Y,Z)) e rotação (Vector3(X,Y,Z)) que informamos. Se você estiver usando uma arma e quiser criar as balas quando atirar, basta dizer que o objetoBala (Um prefab de bala) será criado na mesma posição e rotação da arma (onde estará o script).

Instantiate (objetoBala, transform.position, transform.rotation);

OnCollisionEnter2D

Agora vamos aos sistemas de colisão, onde vocês precisam entender algumas coisas. Para haver colisão você tem que ter adicionado algum Collider2d ao objeto. Ao adicionador, algumas funções estarão ativas. Entre elas o OnCollisionEnter2D, OnCollisionStay2D e OnCollisionExit2D.

O OnCollisionEnter2D será executado uma única vez assim que houve o contato entre o objeto. Se você separar e encostar de novo, irá executar de novo uma única vez no momento em que encostou. Exemplo de uso pode ser ao levar um tiro, a ação irá ocorrer em um único frame assim que a bala encostar o personagem.

	void OnCollisionEnter2D(Collision2D colisor) {
		Debug.Log ("Objeto encostou em " + colisor.gameObject.name);
	}

OnCollisionStay2D

O OnCollisionStay2D, serve para dizer que você está encostando em outro objeto. Exemplo de uso: Puxar ou empurrar caixa é necessário você estar encostado no objeto.

	void OnCollisionStay2D(Collision2D colisor) {
		Debug.Log ("Objeto esta encostado em " + colisor.gameObject.name);
	}

OnCollisionExit2D

Função que ocorre quando deixa de encostar em um objeto, imagine assim: ao encostar em uma porta eu exibo o texto “Aperte E para abrir a porta”. E ao deixar de encostar eu faço esse texto sumir. Então usaríamos o OnCollisionExit2D nesta situação.

	void OnCollisionExit2D (Collision2D colisor) {
		Debug.Log ("Objeto deixou de encostar em" + colisor.gameObject.name);
	}

OnTriggerEnter2D

O trigger funciona exatamente igual ao Collision, a diferença é que a opção Is Trigger tem que estar habilitada. Quando essa opção está habilidade será possível passar por dentro do objeto como se fosse um fantasma ou algo que você possa cruzar e ainda sim irá ser identificando quando um objeto colidiu ou entrou nesse objeto.

	void OnTriggerEnter2D (Collider2D colisor) {
		Debug.Log ("Objeto " + colisor.gameObject.name + " entrou");
	}

OnTriggerStay2D

Stay segue a mesma regra do Trigger, porém ele irá funcionar a cada frame em que um objeto tiver dentro do objeto com o script. Exemplo, criar um posto de gasolina que vai enchendo o tangue do carro enquanto o carro estiver no posto.

void OnTriggerStay2D (Collider2D colisor) {
		Debug.Log ("Objeto " + colisor.gameObject.name + " esta dentro");
	}

OnTriggerExit2D

O Exit acho que você já sabem para que sirva. Será ativado assim que o objeto encostado sair de dentro do objeto principal com o script.

	void OnTriggerExit2D (Collider2D colisor) {
		Debug.Log ("Objeto " + colisor.gameObject.name + " saiu");
	}

OnMouseEnter

O OnMouseEnter significa que você passou o mouse em cima do Objeto. Lembrem-se que isso é diferente de clicar, basta apenas ter passado o mouse por cima.

void OnMouseEnter() {
		Debug.Log ("Mouse passou por cima");
	}

OnMouseOver

O mouse está em cima do Objeto. Vemos muito isso quando tem algum item para pegar no jogo, ao passarmos o mouse por cima ele brilha ou informa que é um item que pode ser pego.

	void OnMouseOver() {
		Debug.Log ("Mouse esta em cima do objeto");
	}

OnMouseExit

Esse outro método informa que o mouse saiu de cima do objeto.

	void OnMouseExit() {
		Debug.Log ("O mouse saiu de cima do objeto");
	}

OnMouseDown

O OnMouseDown significa que você clicou com o mouse no objeto e só executa uma única vez por click.

	void OnMouseDown() {
		Debug.Log ("Clicou com o mouse");
	}

OnMouseDrag

OnMouseDrag significa que você ainda está clicando no objeto (Ainda não soltou o botão) com o Mouse e é executado enquanto você estiver segurando o botão do mouse sobre o objeto.

	void OnMouseDrag() {
		Debug.Log ("Esta clicando com o mouse");
	}

OnMouseUp

OnMouseUp significa que você deixou de clicar no objeto.

	void OnMouseUp() {
		Debug.Log ("Deixou de clicar");
	}

OnDestroy

Para finalizar o MonoBehaviour, temos o OnDetroy que é executado no exato momento em que o objeto deixa de existir.

	void OnDestroy() {
		Debug.Log ("Adeus!!");
	}

Input

Os inputs são responsáveis pelos botões do jogo. Para visualizar quais são os botões você pode ir ao menu do Unity Edit >> Project Settings >> Input.

Esses são os botões padrões do Unity e se você quiser adicionar um novo botão tem que por ai também. Basta aumentar a opção Size e informar o nome do Botão e qual são as teclas que o ativa positivamente e negativamente (Positive Button e Negative Button).

Como pode ver no exemplo acima eu criei um botão “TrocarArma”, onde temos 1 como valor negativo (Volta para arma anterior) e 2 como valor positivo (Avança para próxima arma). Se o seu botão não tiver valor negativo como, por exemplo, o botão “Pular” não tem problema. Caso deseje criar botões alternativos também pode nas opções Alt Negative Button e Alt Positive Button.

GetButtonDown

Acho que você já estão acostumados as 3 etapas de ação (Inicio, processo, fim). Com os botões será a mesma coisa, teremos métodos para quando o botão for clicado, quando o botão estiver pressionado e quando o botão deixar de ser apertado.

O GetButtonDown será ativado uma única vez para cada vez que o botão for pressionado. Exemplo: Comum para usar item, pois o item é usado uma única vez a cada momento em que se clica no botão de usar item, evitando que se use o item mais de uma vez por acidente.

if (Input.GetButtonDown ("TrocarArma")) {
		Debug.Log("Botao TrocarArma foi Pressionado");
	}

GetButton

O GetButton será acionado a cada vez que um frame for executado e que o botão estiver pressionado. (Usado para atirar ou movimentar)

		if (Input.GetButton ("TrocarArma")) {
			Debug.Log("Botao TrocarArma esta sendo Pressionado");
		}

GetButtonUp

Usado quando o botão deixa de ser pressionado.

		if (Input.GetButtonUp ("TrocarArma")) {
			Debug.Log("Botao TrocarArma deixou de ser Pressionado");
		}

GetKeyDown

Mesma funcionalidade do GetButtonDown, só que ao invés de informamos o botão que criamos no Input, iremos informar uma tecla do nosso teclado. No exemplo abaixo a tecla E.

		if (Input.GetKeyDown ("e")) {
			Debug.Log("Tecla E foi Pressionada");
		}

GetKey

Está pressionando uma tecla.

		if (Input.GetKey ("e")) {
			Debug.Log("Tecla E esta sendo Pressionada");
		}

GetKeyUp

Deixou de pressionar uma tecla.

		if (Input.GetKeyUp ("e")) {
			Debug.Log("Tecla E deixou de ser Pressionada");
		}

GetMouseButton

As regras de Key e Button também servem para o Mouse, só que usaremos:

0 – Botão esquerdo

1 – Botão direito

2 – Botão do meio

GetMouseButton é ativado uma única vez por clique assim que o botão é pressionado.

		if (Input.GetMouseButtonDown (0)) {
			Debug.Log("Pressionou o botao esquerdo");
		}

GetMouseButtonDown

GetMouseButtonDown é ativado continuamente enquanto o botão esta pressionado.

		if (Input.GetMouseButton (1)) {
			Debug.Log("Esta pressionando o botao direito");
		}

GetMouseButtonUp

É ativado apenas quando o botão deixa de ser pressionado.

		if (Input.GetMouseButtonUp (2)) {
			Debug.Log("Deixou de pressionar o botao do meio");
		}

GetAxis

Lembra-se de quando criamos o botão informamos o botão positivo e negativo? Bom, o GetAxis serve justamente para dizermos se apertamos o botão positivo (1) ou o negativo (-1).

		if (Input.GetButtonDown ("TrocarArma")) {
			if (Input.GetAxis("TrocarArma") == 1) {
				Debug.Log("Voce apertou o botao positivo");
			} else {
				Debug.Log("Voce apertou o botao negativo");
			}
		}

GetAxisRaw

O GetAxisRaw funciona da mesma forma que o GetAxis, porém ele controla a sensibilidade, sendo assim se você aperta o botão positivo um pouco de leve, ele não dará o valor 1, mas sim por exemplo 0.3. Da mesma forma se você apertar o valor negativo de leve ele irá retornar um valor pouco maior que -1, como -0.5. Apenas quando você aperta todo o botão é que ele dará 1 ou -1. Se você estive usando teclado ao invés do Joytick, a sensibilidade quase não vai existir, então recomendo que diminua a sensibilidade lá no gerenciador do Input.

if (Input.GetButton ("TrocarArma")) {
			Debug.Log ("O valor de Axes de acordo com a sensibilidade e" + Input.GetAxis("TrocarArma"));
		}

mousePosition

Não é um método e sim a posição (X, Y, Z) do mouse. Útil para quando você quer que o seu personagem ande de acordo com o lado que o mouse estiver.

Debug.Log ("A position do mouse e " + Input.mousePosition);

anyKey

Como já deve ter visto lá em cima, anyKey retorna true, caso alguma tecla qualquer seja pressionada. É o clássico: “Pressione uma tecla para continuar o jogo”.

if (Input.anyKey) {
			Debug.Log("Uma tecla esta sendo pressionada");
		}

anyKeyDown

É a mesma ideia do anyKey, a diferença é que retorna true apenas em um frame quando o botão foi pressionado e não continuamente como ocorre com o anyKey.

		if (Input.anyKeyDown) {
			Debug.Log("Uma tecla foi pressionada");
		}

Physics2D

O Physics2D nos permitira trabalhar com alguns recursos relacionados a física do jogo 2D.

Linecast

O Linecast será basicamente igual ao DrawLine da class Debug. A diferença é que no Debug, nós o usamos para criar uma linha que possamos enxergar na aba Scene do Unity, enquanto o Linecast vai verificar se alguma coisa cruzou essa linha.

		if (Physics2D.Linecast (objeto1.transform.position, objeto2.transform.position)) {
			Debug.Log ("Existe algo entre a linha");
		}

Você ainda pode optar por filtrar os tipos de conteúdos que você quer que ele cheque se cruzou a linha através do Layer. Para isso precisa alterar o Layer do objeto que você quer cruze a linha.

E posteriormente no método Linecast adicionar um terceiro parâmetro deixando o nosso script da seguinte forma:

if (Physics2D.Linecast (objeto1.transform.position, objeto2.transform.position, 1 << LayerMask.NameToLayer("Player"))) {
			Debug.Log ("Existe algo entre a linha");
		}

IgnoreLayerCollision

O IgnoreLayerCollision por sua vez é o responsável por fazer com que a collision para de funcionar exclusivamente entre dois Layers. Para que isso é útil? Bom, um dos nossos leitores, Marcos Cruz, precisou que o seu personagem pudesse subir numa plataforma pulando por baixo dela como pode ser visto em alguns jogos do mario ou sonic.

Essas são as plataformas conhecidas como One Way (Única direção), as que você pode passar por baixo dela ou pelos lados, mas quando está em cima não cai. Mas se a gente colocar um collider, sempre vamos colidir não é mesmo? Então podemos simplesmente desabilitar essa colisão quando o nosso personagem estiver pulando. Quando deixar de subir a colisão voltará a ficar ativa:

Physics2D.IgnoreLayerCollision(LayerMask.NameToLayer("Player"),LayerMask.NameToLayer("Piso"), rigidbody2D.velocity.y > 0);

Criando um Layer para o player e adicionando essa linha a seu Script, estaremos informando que não vai haver mais colisão entre o Layer Player e o Layer Piso, quando a velocidade do personagem subindo for maior que zero, ou seja, quando ele estiver subindo no pulo. (rigidbody2D.velocity.y > 0)
Porque é bom criar um Layer só para o Player. Se você desabilitar a colisão do Layer Default e Piso, tudo que tiver nesse Layer irá cair (Objetos, inimgos...)

Mathf

Esta classe será responsável por fazer algumas funções matemática de forma simplificada para a gente.

Abs

Quem se lembra do valor absoluto que aprendemos na escolar e não sabemos para que vamos usar? Oh ai ele aparecendo para você! O método serve para transforma todo valor em positivo. Se tivermos -5, ele irá virar 5.

Debug.Log ("O valor absoluto de -5 e " + Mathf.Abs(-5));

Time

A classe Time consegue nos retornar alguns valores relacionados ao tempo.

time

O time nos retorna os segundos desde que o jogo iniciou.

Debug.Log ("O jogo iniciou em: " + Time.time + " segundos");

deltaTime

O deltaTime nos retorna o tempo que se passou do frame anterior para o frame atual. (Um frame se passa cada vez que o jogo é processado e o update chamado)

Debug. Log("O ultimo frame foi a " + Time.deltaTime + " segundos");

Os computadores possuem velocidades diferentes de acordo com as configurações do PC, desta forma quando formos trabalhar com velocidade de um personagem, é interessante usarmos na multiplicação o valor Time.deltaTime para que a velocidade de um personagem andando seja igual a todos, do contrário um computador melhor executa o “Update” mais vezes do que um computador mais fracos em 1 segundo. Se multiplicarmos esse valor pela velocidade, significa que o computador que executa mais rápido fará com que o personagem ande menos por frame, devido ao seu deltaTime ser menor comparado ao pc mais fraco. Exemplificando:

PC bom que roda 5 Updates (frames) por segundo:

10 (velocidade) * 0.2 (deltaTime) = 2 (Passos)
+ 10 (velocidade) * 0.2 (deltaTime) = 2 (Passos)
+ 10 (velocidade) * 0.2 (deltaTime) = 2 (Passos)
+ 10 (velocidade) * 0.2 (deltaTime) = 2 (Passos)
+ 10 (velocidade) * 0.2 (deltaTime) = 2 (Passos)
Total = 10 Passos em 1 segundo.

PC ruim que roda 2 Updates (frames) por segundo:
10 (velocidade) * 0.5 (deltaTime) = 5 (Passos)
+ 10 (velocidade) * 0.5 (deltaTime) = 5 (Passos)
Total = 10 Passos em 1 segundo.

Entenderam agora a importância de usar o deltaTime quando estamos mexendo com movimento? Senão existisse o deltaTime, o pc bom faria 50 passos em 1 segundo, enquanto o pc ruim faria 20 passos em 1 segundo.

Vector2

O Vector2 nada mais é do que um vetor com duas posição (x, y). O Vector3 então seria um vetor com 3 posições (x,y,z). Bem simples, não?

One

O one retorna um vetor com posição (1, 1)

Debug.Log ("Vector2.one = " + Vector2.one);

right

right retorna um vetor com posição (1, 0)

Debug.Log ("Vector2.right  = " + Vector2.right);

Up

up retorna um vetor com posição (0, 1)

	Debug.Log ("Vector2.up  = " + Vector2.up);

zero

zero retorna um vetor na posição (0,0)

	Debug.Log ("Vector2.zero  = " + Vector2.zero);

E com isso, vocês já devem conseguir fazer bastante coisas dentro da programação do Unity. Essas são todas as classes e métodos? Jamais, provavelmente nem é 1/100 de tudo que o Unity oferece para você que for programar o seu jogo, mas se você souber usar esses vai conseguir usar o resto com tranquilidade também.

À medida que fomos utilizando mais conteúdos em nossos tutorais eu posso atualizar esse post aqui ou criar outro tutorial extra de programação, se vocês preferirem.

Por enquanto, minha recomendação é crie um projeto de teste e tentem usar todos essas classes, métodos e variáveis, que já será um super treino para vocês se acostumarem com a programação do jogo.

Então é isso pessoal, espero que tenham gostado. Sugestões, dúvidas deixem ai nos comentários e até o próximo tutorial!

Indice Unity

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

35 comments

  1. Bruno disse:

    Cara, como sempre com a qualidade lá em cima! Ótimo tutorial e valeu por tornar mais frequente, pra quem acompanha faz toda a diferença!

  2. Otávio disse:

    Caramba meu obrigado!!!! Seus tutoriais deram uma ajuda no meu game!!

  3. Ótimo tutorial, agradeço muito as aulas =D

  4. Victor Hugo disse:

    Eu posso usar o invoke para chamar um função depois de x tempo?
    ou somente para exibir uma frase depois de x tempo?

    • Opa Hugo 😉

      Então, o Invoke o papel do Invoke na realidade é chamar uma função. Nós usamos o termo entre aspas dupla (String), mas ele esta chamando uma função com aquele nome, entendeu?

      Ai dentro dessa função você pode fazer o que quiser: Exibir um texto, explodir uma bomba, dá game over…

      • Victor Hugo disse:

        cara… eu não sei esta certo, mas eu usei o invoke para dar um delay pro meu ataque ataque sair depois da minha animação, tem algum problema?
        tipo… o personagem faz um movimento com as mãos quando vai lançar uma magia.
        antes eu tava apertando e a magia estava saindo antes da animação acabar, com o invoke eu atrasei a saída da magia, tem algo errado nisso? deve dar algum problema no futuro?

        • Não há problema algum Hugo. Pode ser feito assim desta forma sim.

          Agora se o time for muito grande, se o seu personagem levar dado e animação for cortada (Se mudar de animação quando recebe dano) ai sim, seria bom você usar o cancelInvoke, para evitar ataques cancelados.

          • Victor Hugo disse:

            muito obrigado, eu tenho só mais uma duvida rs, ta tudo funcionando perfeitamente, pelo menos por enquanto rs, mas… quando eu mando atacar para direita vai tranquilo, quando mando atacar para esquerda meu personagem após atacar dá um pequeno recuo para a direita ‘-‘, como se fosse 1 passo pra trás depois de cada ataque ‘-‘, antes de colocar o sistema de colisão ele ficava normal, atirava tanto pra direita quanto para a esquerda e permanecia no mesmo local, após o sistema de colisão quando atiro pra esquerda ele anda 1 passo pra direita =s. Por enquanto isso não esta me incomodando em nada, porém se no futuro eu o colocar para atacar de uma plataforma provavelmente ele cairá xD

    • Não dá para comentar mais no comentário de baixo, então explicando a sua dúvida de dar um passo para trás.

      Eu acredito que isso seja o objeto que você está instanciado. Sabe aquela regra da física dois corpos não podem ocupar o mesmo espaço? Como os dois tem collider, significa que os dois não podem ocupar o mesmo espaço. Ai o objeto que está sendo instanciado está empurrando o personagem para trás.

      Creio que seja isso, tente instanciar o objeto um pouco mais afastado do seu inimigo/personagem 😉

  5. Melhor tutorial que encontrei sobre programação na Unity. Foi como um mapa conceitual para entender de tão organizado que foi feito e organizado.

  6. Gustavo Lima disse:

    amigo eu queria saber como eu atiraria na posição do mouse, estou trabalhando em um top down shooter 2d

    • Então cara, fazer isso em jogos 3D é bem fácil, basta usar o LookAt. Porém nós no mundo 2D, sofremos um pouco mais. Eu fiz aqui o seguinte script que vai te ajudar:

      void Update () {
      LookAtMouse ();

      if (Input.GetButton (“Fire1”)) {
      Instantiate(bala, transform.position, transform.rotation);

      }
      }

      private void LookAtMouse() {
      Vector3 dir = Input.mousePosition – camera.main.WorldToScreenPoint(transform.position);
      float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
      transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
      }

      O LookAtMouse vai fazer o seu personagem rotacionar apenas em Z, afinal você disse que era um top down, logo só mexe em Z.

      o Instantiate ali é para fazer a bala (Se for uma metralhadora), onde ele vai sair da posição do seu personagem e na rotação que ele estiver.

      Na bala você pode criar um script bem simples mesmo como já vimos aqui:

      public float velocidade = 5f;

      // Use this for initialization
      void Start () {
      Destroy (gameObject, 5f);
      }

      // Update is called once per frame
      void Update () {
      transform.Translate (Vector2.right * velocidade * Time.deltaTime);
      }

      Basicamente é isso. Só transforma sua bala é um prefab, bota os colliders e seja feliz o/

      Ficou assim no meu:
      http://jogosindie.com/wp-content/uploads/2015/01/shooter.jpg

  7. Romario Gomes disse:

    Muito bom Cara, estou começando seus tutoriais agora e pelo que vi são de ótima qualidade. Continue assim!

  8. Wagner Luiz disse:

    Carlos, Tutorial nota 10, me ajudou muito na questão conceito das funções.

  9. Anderson disse:

    Carlos meus parabéns, fantástico esta ajudando muito, meu muito obrigado

  10. Rodrigo disse:

    Oi ^^ Sou novo nessas coisas de criar games, mas, é que eu fiquei pensando “Seria legal eu msm criar um jogo…” Enfim, por enquanto, estou criando só as habilidades do meu personagem, e, quando quero fazer ela ser lançada pelo meu personagem, fica dando erro toda hora ¬¬
    Olha como eu fiz o script:
    void Update () {
    if (Input.GetButton (“Fire1”)) {
    Instantiate (?????, transform.position, transform.rotation);
    }

    }
    }
    O nome do prefab que quero usar é “comets”. Mas o que eu coloco nesses “?????” para funcionar? Tentei colocar gameObject, GameObject, comets e sempre dá erro… AAAAAHH!

  11. no caso você coloca um GameObject, Rodrigo.

    crie um public GameObject comets

    E no Instantiate coloque o GameObject
    Instantiate(comets, transform.position, transform.rotation);

    No tutorial do inimigo 2, temos exatamente esse exemplo que você quer ^^

  12. claudio disse:

    eu to começando agora e gostaria de saber se tem como usar acelerômetro em 2d , tipo no piso onde eu movimento celular o piso movimenta tipo em rotação de uma helice mas visto de cima ..

  13. Muito bom cara, foda achar conteúdo bom assim em português.

  14. Valeu Henrique ^^

    E Claudio não sei responder, mas acredito que o Unity deve ter sim algum recurso de acelerômetro.

  15. renan disse:

    Ótimo Artigo. Há tempo procuro por algo assim.

  16. carloswgama disse:

    Valeu Renan ^^

    Temos mais posts do Unity caso não tenha visto o/

  17. jrdiebe disse:

    Parabéns! Conteúdo excelente!

  18. Maycon disse:

    Fala, Carlão… obrigado pelos tutoriais, cara.
    Você manja bastante de programação e fico feliz pela sua pessoa ser humilde e gostar de todas as coisas que eu gosto. ><
    Eu 'tô desenvolvendo um jogo que vai revolucionar educação no país, e sempre pego umas dicas aqui.
    Então acho que posso compartilhar uma com você, que acredito até que já saiba.
    Eu não preciso usar o metódo IgnoreLayerCollider.
    Já existe um componente chamado Platform Effector 2D que tem a opção de "One Way" dentro dele.
    Obrigado, cara.
    Vou continuar acompanhando seu tuto.
    Inclusive vou fazendo desde o início mesmo sabendo boa parte.
    Conhecimento nunca é demais.

    • Opa cara, muito massa ^^

      Quanto ao Platform One Way do Platform Effector, estou por dentro sim. Eu ensino ele no primeiro cenário do tutorial intermediário ^^

      Na versão 4.6 que ainda não existia. E isso quebra um galho danado.

  19. Filipe Sousa disse:

    Parabéns Jogos indie, como sempre ajudando a muitos. Muito Obrigado mesmo, agora já estou com um bom embasamento. Agora é só praticar e estudar mais um pouco. Mais uma vez… MUITO obrigado mesmo. 😀

  20. Hugo E.R. Ferreira disse:

    Excelente post Carlos. Vi muitas coisas que não sabia. Essa coisa da programação sempre tem alguma função desconhecida que faz a mágica que você precisa, o problema é que na maioria das vezes desconhecemos várias funções. Mesmo tendo boa base em programação, vira e mexe estou na internet procurando como fazer alguma que não sei. Geralmente quando acho o código pronto, vem com algum método ou função que eu desconhecia.

  21. neto miranda disse:

    muito bom este tutorial !!

  22. Ana Vitória disse:

    OIII , então, meu personagem colide com um objeto e destrói, já tentei de todas maneiras possíveis,mas não destrói, poderia me ajuda?

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!