Unity 5. Programando Interações simples

Neste tutorial iremos aprender a controlar, programaticamente, propriedades simples de objectos através do rato, designadamente as três principais transformações do espaço cartesiano, a translação, a escala e a orientação ou rotação.

No unity existem duas linguagens nativas, o javascript e o C#. No decurso deste tutorial, usaremos esta última linguagem.

Antes de começarmos, e tratando-se este post de um exercício de iniciação, vamos introduzir alguns conceitos e explicar como os scripts são introduzidos no Unity.

Os scripts podem ser criados de várias formas:

i) no painel assets, com o botão de lado direito, o comando Create – C# Script

ii) no menu Create, o comando Create – C# Script.

iii) após seleccionar um objecto, o comando Add Component, localizado no painel Inspector.

Este último modo, ao contrário do primeiro, associa automaticamente o script ao obejcto. Nos dois primeiros casos, é necessário ainda arrastar o script para cima do objecto 3D no palco ou, directamente, para o painel Inspector.

Em geral um script define o comportamento de um obejcto e deverá ser concebido de modo a ser reutilizado ao longo de vários momentos da aplicação e para obejctos distintos. Por exemplo, se tivermos 3 cubos no palco e necessitamos de um programa que faça rodar um obejcto sempre que é clicado por parte do utilizador, não faze sentido criar 3 scripts iguais. A prática usual consiste em conceber um comportamento genérico que será associado individualmente a cada um dos objectos. Por essa razão, ao longo de um script recorremos ao pronome this em lugar do nome próprio, sempre que queremos referir-nos ao objecto.

 

 

Criar um comportamento de rodar sobre si mesmo sempre que é clicado

Comecemos por criar 3 cubos e posicioná-los, lado a lado no palco. Atribuimos os nomes “cubo esq”, “cubo centro” e “cubo direito”, respectivamente.

unity_5_interacao_figura1

Em seguida, criamos um script no painel assets e atribuimos o nome “rodame”. Fazendo duplo clique sobre o seu ícone, no painel assets, o editor MonoDevelop (EMD) carregará o script acabado de criar.


using UnityEngine;
using System.Collections;

public class rodame : MonoBehaviour {

// Use this for initialization
void Start () {

}

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

}
}

Uma classe é criada automaticamente para o script em questão, com dois eventos especificados, o evento start e o evento Update (uma classe é um mecanismo de programação orientada a objectos e por agora não é necessário o seu entendimento). Um evento é uma função que é chamada automaticamente pelo Unity, no caso do Start o evento é evocado apenas uma única vez, quando a aplicação ou o jogo tem início. Este evento é muito útil para incializar variáveis, objectos e dados da aplicação no seu início. Já o evento Update é evocado com a mesma frequência da framerate, ou seja, várias vezes por segundo.

 

Comando Print

Os comandos print e debug.log são idênticos e tem como função escrever na janela Console permindo dar a conhecer ao programador o valor de certas variáveis e assim monitorizar o correcto funcionamento do código.

Introduza o seguinte comando no bloco do evento start:

print “olá, a aplicação começou!”

Em seguida grave o ficheiro (save) e no unity, arraste script para o cubo do centro.

Ao correr a aplicação (Mode run) a mensagem “olá, a aplicação começou!” aparecerá uma única vez no painel Console.

 

Adicionar eventos

Além dos eventos Start e Update, outros eventos podem ser adicionados, como por exemplo OnMouseUp e OnMouseDown, os quais, como o próprio nome indica, são evocados sempre que o utilizador clica ou larga o botão do rato sobre o objecto.

Vamos então adicionar ao nosso exemplo o evento OnMouseUp e no seu interior colocar o comando print “clicaste-me!”.


using UnityEngine;
using System.Collections;

public class rodame : MonoBehaviour {

// Use this for initialization
void Start () {
print ("olá, a aplicação começou!");
}

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

}

void OnMouseUp(){
print ("clicaste-me!");
}
}

Grave o script no editor e corra a aplicação. Sempre que carregar com o botão esquerdo em cima do cubo do centro a mensagem “clicaste-me!” surge no painel Console.

 

 

OFF-TOPIC. Componente Colider

Para usar a funcionalidade do evento OnMouseUp e OnMouseDown no unity é necessário adicionar previamente ao obejcto 3D o componente colider, caso contrário, o evento OnMouseUp não é evocado. Isto apenas para o caso de objectos 3D importados, já que os objectos criados dentro do Unity, têm por omissão o componente previamente adicionado na sua pilha de componentes , visível no painel Inspector.

O componente Colider consiste numa bounding box (ou numa outra forma primitiva como por exemplo a esfera ou o cilindro), e tem por função definir para o obejcto 3D um volume sensível a colisões com o rato ou com outros elementos e obejctos 3D. No unity, é necessário associar este comportamento a todos os objectos sempre que prentendemos monitorizar colisões deste obejcto com outras entidades da simulação. A razão deve-se ao facto das colisões exigerem um esforço em termos de processamento e que, deste modo, para os objectos estáticos pode ser poupado à aplicação.

Para adicionar selecione o obejcto importado no painel Inspector adicione um novo componente. Escolha a categoria Physics e em seguida o componente Box Colider.

 

 

Transformação geométricas do objecto.

A posição, a escala e a rotação do objecto pode ser controlada programaticamente através do objecto transform. Como se trata de uma simulação tridimensional, cada uma destas propriedades possui 3 dimensões, por essa razã, a variável vector3D será bastante útil.

Vejamos a sintaxe para, respectivamente, incrementar a posição, a escala e a orientação em uma unidade no eixo y:


this.transform.Translate(new Vector3 (0, 1f, 0);
this.transform.localScale += new Vector3 (0, 0.01f, 0);
this.transform.Rotate (new Vector3 (0, 1f, 0));

Coloque, à vez, cada uma destas linhas de código no evento Update e analise o resultado.

Exemplo para o caso da última da função Rotate:


using UnityEngine;
using System.Collections;

public class rodame : MonoBehaviour {

// Use this for initialization
void Start () {
print ("olá, a aplicação começou!");
}

// Update is called once per frame
void Update () {
this.transform.Rotate (new Vector3 (0, 1f, 0));
}

void OnMouseUp(){
print ("clicaste-me!");
}
}

unity_5_interacao_figura2

Repare que a escala não tem uma função própria para se incrementar, ao contrário da transformação da posição que tem a função Translate e a rotação que tem a funcção Rotate.

Contudo, se necessitarmos de posicionar em termos absolutos o objecto 3D em questão usamos a propriedade localPosition e não a função de incremento Translate. O mesmo para o caso da orientação, que através da propriedade eulerAngles podemos controlar em termos absolutos a orientação.


this.transform.position = new Vector3 (0, 1f, 0);
this.transform.eulerAngles = new Vector3 (0, 1f, 0);

 

 

Rodar o objecto apenas quando se clica.

Vamos criar um script que sempre que o utilizador clica no objecto ele roda a uma certa velocidade e pára quando voltamos a clicar nele.

Precisamos de uma variável para a velocidade e outra que permite comutar entre o estado a rodar e o estado parado.


float velocidade = 0.5f;
bool rodando=false;

No evento OnMouseUp comutamos o estado da variável rodando, invertendo o seu valor lógico:


rodando = !rodando;

<span style="line-height: 1.7;">

Por fim, no evento Update condicionamos o comando Rotate ao estado da variável rodando:


if (rodando) this.transform.Rotate (new Vector3 (0, velocidade, 0));

Integrando todos este passos o nosso script ficará com o seguinte aspecto:


using UnityEngine;
using System.Collections;

public class rodame : MonoBehaviour {

float velocidade = 0.5f;
bool rodando=false;

void Start () {
}

void Update () {
if (rodando) this.transform.Rotate (new Vector3 (0, velocidade, 0));
}

void OnMouseUp(){
print ("rodando=" + rodando );
}
}

Grave o script no editor e corra a aplicação no Unity. Associe o mesmo script aos três cubos.

Criámos um script genérico que tem como principal vantagem ser reutilizável para objecto 3D. Podemos deste modo criar um conjunto de scripts que vão constituindo um património valioso não apenas para o presente mas também em futuros projectos.

Consideremos agora um novo cenário: pretendemos que a velocidade seja diferente para cada um dos objectos. Será que devemos abandonar esta ideia de encapsulamento e reutilização do código e sermos forçados a criar 3 versões diferentes do script, cada uma com um valor diferente atribuído à variável velocidade ? Não seria nada prático repetir 3 vezes o processo sempre que tivéssemo necessidade de alterar o código.

A fórmula correcta para resolver este problema consiste em recorrer a uma variável pública, a qual caracteriza-se por ficar exposta e poder ser editada na interface do Unity.

Coloquemos então o prefixo public imediatamente antes da declaração da variável velocidade:


public float velocidade = 0.5f;

vejamos o que acontece na vista do componente do script no painel Inspector.

unity_5_interacao_figura3

Agora podemos, livremente, atribuir diferentes valores à velocidade de rotação para cada um dos cubos.

Controlar propriedade de outros objectos

Em certas situações é necessário controlar as propriedades de outros objectos 3D a partir do script de um outro objecto. Por exemplo, se quisermos aumentar a escala do objecto que é clicado mas, ao mesmo tempo, diminuir a escala do restantes. Nestes casos, teremos de subsituir o pronome this por uma função que represente outros objectos em cena. A função em questão é a Find do objecto GameObject.


GameObject.Find(“cubo esq”).localScale = new Vector3 (0.5f, 0.5f, 0.5f);

Esta instrução permite a qualquer script aumentar 50% da escala do objecto cubo esq em particular.

Crie um programa que aumente o objecto clicado e diminua os restantes.

Anúncios