Colisões :: GameDev receitas Unity3D

Detetar colisões entre objetos é uma prática fundamental para (quase) todo jogo eletrônico.
Além de detetar as colisões, é importante saber o que fazer, depois que elas ocorrem.
As game engines, sempre possuem recursos para a deteção de colisões, e esse é um tópico muito importante de ser observado, antes de escolher qual game engine utilizar para seu projeto.

Em linhas gerais, os pontos básicos a serem observados são:
– como se configura a deteção de colisão;
– quais geometrias de colisão (esferas, cubos, planos …) são disponibilizados pela engine;
– Se a game engine, permite deteção de colisão com geometria 3D (mesh).

Quando as colisões são detetadas, em geral, eventos são disparados pelo sistema. E esses eventos, podem ser capturados por objetos de jogo; que iniciam funções, para gerar a dinâmica do jogo.

Para esses exercícios no Unity3D, monte uma cena como descrita na imagem abaixo:
CenaCollisions
Obs.: Durante o tutorial, vou utilizar os nomes dos elementos como estão marcados na imagem acima.

No Unity3D, as deteção de colisões são realizadas pela engine de física, portanto, os elementos necessários para a deteção estão localizados no menu Componet >> Physics, são eles os Colliders e o Rigidbody.

Para começarmos o demo, vamos adicionar e configurar os elementos básicos necessários.
Observe no objeto SphereTrigger, se há o component SphereCollider, e se esse component está marcado como um Trigger. Caso não haja o componente collider, para adicioná-lo, selecione o objeto SphereTrigger, vá ao menu Component >> Physics >> Sphere Collider. E para marcá-lo como trigger, vá ao componente no painel Inspector, e selecione a opção “Is Trigger”.

O objeto Cube, irá desempenhar um papel importante nesse demo, ele andará pela tela com os comandos do usuário, e irá demonstrar o funcionamento das colisões. Para configurá-lo, verifique se o mesmo possui o componente Box Collider, porém esse não pode ser marcado como um trigger. Adicione também ao Cube, o componente Rigidbody. Para adicionar tal componente, selecione o Cube, vá ao menu Component >> Physics >> Rigidbody. E nesse caso é importante marcar a opção “Is Kinematic”, isso nos permitirá mover o Cube, sem a necessidade de simulações de física.
Para finalizar, basta adicionar dois scripts ao cubo; Primeiro o script BasicInputHandlerCube, que você encontra no tutorial sobre Inputs de Usuário; O segundo script a ser adicionado é o script abaixo:

BasicCollisionHandlerCube:
[code lang=”java”]
private var colisionInfo:String = “Collision info”;
function Update () {
}

function OnCollisionEnter(col : Collision){
colisionInfo = “Collision Enter (Rigidbody) : “;
}

function OnCollisionExit(col : Collision){
colisionInfo = “Collision Exit (Rigidbody) : “;
}

function OnTriggerEnter(col : Collider){
colisionInfo = “Collision Enter (Trigger) : “;
}

function OnTriggerExit(col : Collider){
colisionInfo = “Collision Exit (Trigger) : “;
}

function OnTriggerStay(col : Collider){
colisionInfo = “Collision Stay (Trigger) : “;
}

function OnGUI(){
GUI.Label(Rect(200,75,300,100),colisionInfo);
}
[/code]

Após esse trabalho, quando você executar o jogo, verá na parte central da tela, um texto exibindo algumas informações sobre a colisão, quando ela existir.
O que acontece é o seguinte. Como dito anteriormente, o Unity3D, realiza as colisões usando a engine de física, logo, os Colliders são os “sensores” que são usados para calcular quando um “toca” ou “permeia” a àrea de outro collider. Quando esse toque é detetado, o componente Rigidbody dos objetos é informado, e envia uma mensagem para o gameObject que pode ser: OnCollisionEnter, OnCollisionStay, OnCollisionExit, OnTriggerEnter, OnTriggerStay, ou OnTriggerExit.
No caso de uma colisão com um trigger, que é o caso do objeto SphereTrigger, serão enviadas as mensagens OnTriggerEnter, quando a colisão se iniciar; OnTriggerStay, enquanto a colisão estiver em curso; OnTriggerExit, quando os objetos param de colidir.
No caso de uma colisão com um rigidbody, serão enviadas as mensagens OnCollisionEnter, OnCollisionStay, e OnCollisionExit, seguindo os mesmos princípios das colisões com Triggers.

Portanto, o que script faz é o seguinte, quando uma mensagem de colisão é enviada, o script BasicCollisionHandlerCube acionará a função apropriada à colisão, e irá mudar o texto da mensagem que aparece na tela, informando se a colisão foi com um Trigger, ou com um Rigidbody.

Para fazer a colisão com um rigidbody, vamos cofigurar o objeto SphereObject. Verifique se se a SphereObject, possui um SphereCollider (não trigger), e um Rigidbody (não kinematic).
Então use o Cube, para colidir sobre esse objeto e veja o resultado. Você verá que a esfera, não irá se interpolar com o Cube, e ainda irá reagir como uma bolinha sobre o plano.

Veja o exemplo final aqui.

As outras esferas que temos nas cenas, podem ser configuradas como lhe interessar. Use-as para experimentar.

Mensagens :: Gamedev receitas Unity3D

Para enviar mensagens de eventos entre objetos de jogo no Unity3D, há duas possibilidades: 1 – Enviar a mensagem para os objetos com parentesco; 2 – Fazer uma busca pela cena para encontrar objetos de jogo, e executar um componente.

Mensagens
Inicialmente, vejamos o primeiro modo, com objetos agrupados usando dos método, SendMessage, BroadcastMessage, e SendMessageUpwards.
Para começar, criamos uma cena com elementos básicos como descrito na imagem abaixo:
imagemCenaMessages
Obs.: Monte sua cena com elementos semelhantes a esses, e dê os mesmos nomes. Os objetos fountain, e cannon, devem possuir um EllipsoidParticleEmitter, um ParticleRender e um ParticleAnimator, configure-os como quiser.
Obs 2.: No objeto Cube2, utilize o script BasicInputHandler, visto no tutorial sobre Inputs de usuário.

SendMessage
O método SendMessage irá executar uma determinada função em qualquer componente do gameObject que enviou a mensagem.
No objeto fountain, coloque o seu BoxCollider Component como um trigger. Crie esses dois scripts, e os arraste para o gameObject.

FountainScript:
[code lang=”java”]
function Update () {
}

function TurnFountainOn( v: boolean){
particleEmitter.emit = v;
}
[/code]

SendSimpleMessageScript:
[code lang=”java”]
function Update () {
}

function OnTriggerEnter(col: Collider){
this.SendMessage(“TurnFountainOn”, true);
}

function OnTriggerExit(col: Collider){
this.SendMessage(“TurnFountainOn”, false);
}
[/code]

Ao arrastar esses scripts para o gameObject fountain, eles se tornam Components. O SendSimpleMessageScript irá detectar colisões com o seu BoxCollider (setado como um trigger), e na entrada e saída das colisões irá executar o envio de mensagem “TurnFountainOn”, junto com um valor boleano true ou false.
O FountainScript, possui a função TurnFountainOn, que irá ligar, ou desligar a emição de partículas, de acordo com o recebimento do parámetro true ou false.
Veja mais detalhes nesse link.

BroadcastMessage
O método BroadcastMessage fará o mesmo que o método SendMessage, porém com a possibilidade de enviar as mensagens para outros gameObjects, desde que esses gameObjects sejam filhos do objeto que enviar as mensagens.

Para essa etapa, arraste o gameObject cannon sobre o objeto cannonPlat (faça isso no painel, não na cena de jogo), para que ele seja um “filho” do cannonPlat.
Arraste o script FountainScript para o objeto cannon.
No objeto cannonPlat, configure seu BoxCollider como um trigger.

Crie um novo script, BroadcastMessageScript:
[code lang=”java”]
function Update () {
}

function OnTriggerEnter(col: Collider){
this.BroadcastMessage(“TurnFountainOn”, true);
}

function OnTriggerExit(col: Collider){
this.BroadcastMessage(“TurnFountainOn”, false);
}
[/code]

Esse script funciona basicamente como o SendSimpleMessageScript, detecta colisões com seu trigger, e chama a função TurnFountainOn, em qualquer objeto que seja “filho” do objeto cannonPlat.

Find Component
Todo gameObject no Unity3D pode executar a função Find, que irá procurar por gameObjects pela cena. Dessa busca, os Components dos objetos são acessíveis, e podemos executar funções pertencentes à eles.

Para essa etapa, configure o BoxCollider do objeto plat, como um trigger. Adicione o FountainScript ao objeto cannon.

Crie o seguinte script, FindBehaviorScript:
[code lang=”java”]
function Update () {
}

function OnTriggerEnter(col: Collider){
GameObject.Find(“cannon”).GetComponent(“FountainScript”).TurnFountainOn(true);
GameObject.Find(“fountain”).GetComponent(“FountainScript”).TurnFountainOn(true);
}

function OnTriggerExit(col: Collider){
GameObject.Find(“cannon”).GetComponent(“FountainScript”).TurnFountainOn(false);
GameObject.Find(“fountain”).GetComponent(“FountainScript”).TurnFountainOn(false);
}
[/code]

Arraste o script para o objeto plat. Assim como os scripts anteriores, esse script irá atentar para colisões, e então, Pesquisar na cena pelos objetos cannon, e fountain. Com esses objetos localizados, o script busca pelo componente FountainScript, e então executa a função TurnFountainOn.
Veja esse link para mais informações.

Veja aqui o exemplo final.

Inputs de Usuário :: GameDev receitas Unity3D

Inputs e eventos, são elementos comuns em desenvolvimento de software como um todo. Afinal todo, ou quase todo, software recebe uma ordem de execução, através de um clique, ou de um comando de teclado, e essa ordem vinda de um usuário, chamamos popularmente, de Input de usuário.
Eventos são, em geral, comandos trocados entre elementos de um software. No caso de um jogo, podemos imaginar a seguinte situação: Um personagem está andando por um castelo, onde há um “gatilho” de uma armadilha. Quando o personagem, passa pelo gatilho, o gatilho avisa a armadilha para disparar as flechas que matarão o personagem.
Nessa pequena descrição, podemos dizer que o gatilho, enviou uma mensagem para a armadilha disparar. Essa mesagem é o que chamamos de eventos.

Ambos, Inputs de usuário, e eventos entre objetos, possuem um papel primordial para a construção de um jogo.

Input de Usuário ::
Crie um novo script Javascript no painel “Project”, chamado BasicInputHandler, e acoloque o seguinte código:
[code lang=”Javascript”]
function Update () {
//Move o objeto pelo eixo Z
if(Input.GetAxis(“Vertical”) > 0){
transform.Translate(Vector3.forward * Time.deltaTime);
}
else if(Input.GetAxis(“Vertical”) < 0){
transform.Translate(- Vector3.forward * Time.deltaTime);
}

//Move o objeto pelo eixo X
if(Input.GetKey(“d”)){
transform.Translate(Vector3.right * Time.deltaTime);
}
else if(Input.GetKey(“a”)){
transform.Translate(- Vector3.right * Time.deltaTime);
}
}
[/code]
Adicione um cubo à sua cena, e arraste esse script para esse cubo.

Esse script está checando o Input de usuário de duas formas, a primeira pelo eixo “Vertical” do objeto Input, e outra pelas teclas ‘d’ e ‘a’.

Veja o exemplo aqui.

Opção de Eixos.
No Unity3D, há esse objeto global chamado Input, que captura as entradas de usuário, e às torna acessíveis para outros objetos do jogo. Esse eixo “Vertical”, que o objeto Input está utilizando, é previamente configurado, para ser ativado pelas teclas W,S, seta-para-cima e seta-para-baixo: As teclas W e Seta-para-cima, fazem com que o eixo “Vertical” seja positivo; As teclas S e Seta-para-baixo, fazem que o eixo seja negativo.
ISSO É UM CONFIGURAÇÃO QUE PODE SER MODIFICADA pelo desenvolvedor. Se você preferir que outras teclas acionem o eixo Vertical, entre no menu EDIT >> Project Settings >> Input. O painel Inspector irá exibir os eixos previamente configurados no Input. Você pode modificar as configurações de cada um deles, criar e excluir os eixos (basta modificar a propriedade Size, se você aumentar terá mais eixos disponíveis, se reduzir, eixos serão deletados).

Opção de Teclas.
A outra opção de utilização do Input, é pela função GetKey. O objeto Input captura quando as teclas são pressionadas, e essa informação fica disponível para a utilização.

Ambas as formas de captura do Input são válidas. A diferença entre elas é um detalhe, que não é muito claro de início, mas que vou descrever abaixo:
No objeto Input, do Unity3D, quando uma tecla que está ligada à algum eixo, é pressionada (digamos a tecla W), o eixo em questão começa a “crescer”, seu tamanho inicial que é zero, começa a aumentar; E quando a tecla é solta, o eixo começa a diminuir, seu tamanho diminui até chegar a zero.
Imagine essa situação no nosso cubo:
Assim que o usuário pressiona, digamos a tecla W, o eixo “Vertical” começa a crescer em comprimento, e o Cubo então, começa a se deslocar, afinal nosso código desloca o objeto quando o tamanho do eixo for diferente de zero. Mas assim que o usuário solta a tecla que ativa o eixo, o eixo começa a diminuir de tamanho lentamente, o que faz com que o nosso objeto continue se movendo, e interrompa seu deslocamento, apenas quando o eixo chegar ao valor zero.

Com o código acima, você perceberá, que há uma diferença entre as animações do movimento do cubo pelo eixo X e Z. Qual é o certo de ser usado? Depende de você escolher!

 

Update :: GameDev receitas Unity3D

“Updates”, é uma nomenclatura usada no Unity3D, que se refere: “A necessidade de prover a certos objetos de jogo, loops de execução.”

Por exemplo, ao se criar um personagem em um jogo, a programação desse personagem pode ter uma série de funções que devem ser checadas, e executadas, a cada frame do jogo.

Diferentes game engines, possuem diferentes nomenclaturas, e formas de se implementar esses procedimentos. Aqui veremos como funciona no Unity3D. Na verdade o conceito é simples, basta usar a função Update, nos seus scripts.

Cria uma cena no Unity, e adicione dois cubos à cena, e posicione-os como preferir. Mas nomeios com os nomes “Cubo1” e “Cubo2″.

[code lang=”javascript”]
private var teste:int = 0;

function Update () {
Debug.Log(“Frame : “+teste);
teste++;
}
[/code]
Obs.: Crie esse script, nomeie-o como quiser. Arraste o script, do painel “Project”, para um dos GameObjects que estejam na sua cena (de preferência um dos cubos). Ao rodar o script, você vera esses resultados na janela do “Console”.

Esse script, está contando o número de frames do seu jogo. Logo na primeira linha, criamos a variável ‘teste’, com valor 0. A função Update, será executada a cada loop do programa, e a cada loop, ela irá escrever no Console a mensagem: “Frame : 0”, “Frame : 1”; “Frame : 2″… e assim sucessivamente

Agora para fazer com que um objeto de jogo se desloque na cena, façamos o seguinte script:

[code lang=”javascript”]
private var teste:int = 0;

function Update () {

transform.Translate(Vector3.right * Time.deltaTime);
Debug.Log(“Frame: “+teste);
teste++;
}
[/code]

Execute seu jogo, e você verá, o seu cubo se deslocando aos poucos sobre o eixo X, no sentido positivo do eixo.
Veja o exemplo aqui.