[Unity 3D] Tutorial para novatos (4 – Colisiones)

burnout_dominator__ps2_game_Retomando el blog, y viendo que lo más útil del blog están siendo los artículos de Unity entonces continuaré con los mismos intentando abarcar una mayor cantidad de temas que puedan ser especialmente útiles al querer comenzar a desarrollar nuestro propio primer juego.

Considerando los artículos anteriores, pudimos ver un pantallazo de los tópicos principales: la interfaz del programa, la creación de objetos y la programación de los mismos para que hagan cosas.
Ahora otro de los temas que es muy útil a saber y que se debe usar el 80% del tiempo son las colisiones.

Parte 1 – Objetos:

Inicialmente lo que nos debemos plantear es que objetos requerirán ser detectados para realizar una cierta acción. Para ello nos preguntamos, ¿el personaje deberá interactuar con este objeto? ¿es parte del escenario sobre el cual se moverá el personaje, como son las plataformas, el piso, el techo, las paredes? ¿el objeto deberá eliminarse en contacto con otro?, entre otras. Una vez que tenemos la respuesta a esas preguntas, ya sabemos que objetos deberán contener el componente necesario para detectar colisiones.

unity18Entonces, ahora agregaremos el mismo dentro de un objeto que sabemos que lo necesitará. En este caso vamos a considerar que es el piso del escenario. El componente requerido para detectar las colisiones dependerá de la forma que tiene el objeto que vamos a considerar como «colisionable». En la imagen podemos ver un extracto del Inspector de un objeto, dentro del cual presionamos el botón Add Componente que figura al final del mismo, y luego escribimos «Col» para que nos muestre justamente todos los componentes que posean dichas letras en su nombre. En este caso podemos ver aquellos que tienen como parte del nombre la palabra Collider y son justamente los que se encargarán de detectar las colisiones. Si prestamos atención a los nombres, estos indican la forma que tendrá nuestro detector de colisión. La idea es que se seleccione la forma que mas se adapte al objeto en cuestión. En nuestro caso, el piso estará compuesto por un objeto con forma de caja alargada, por lo que elegiremos el Box Collider.

Observar que figuran Colliders que poseen en su nombre las siglas 2D. Estos se utilizan cuando a la hora de realizar un juego, este se piensa que sea justamente 2D.

unity20Una vez que pulsamos el Collider que nos interesa, veremos algo como esto ->

Dentro de las cosas que podemos observar dentro del componente tenemos:

  • Edit Collider: pulsando el botón que tiene 3 cuadrados unidos por líneas, accedemos a modificar la caja de colisión. Esta caja indicará el detector de la colisión, es decir que la colisión tendrá a lugar recién cuando estas cajas se estén tocando y NO cuando los objetos se estén tocando. Podemos agrandarla, achicarla, modificarla en cualquiera de sus ejes. Para ello veremos algo como la figura de abajo. Se ve en ella como hay una caja de color verde además del objeto. Ésta es la caja de colisiones y podemos retocarla agarrando los cuadraditos verdes que figuran en cada una de sus caras.
  • Is Trigger: cuando está activada esta opción, quiere decir que el colisionador no se activará en caso que un RigidBody esté en contacto con él (el componente RigidBody le atribuye características físicas a un objeto). Se suele activar esta opción cuando no se quiere que la colisión impida que los objetos involucrados se superpongan, dicho de otra manera, se quiere que los objetos involucrados puedan superponerse.
  • Material: No funciona al igual que la característica Material de los objetos en la cual se le atribuyen colores o reflejos, sino que atribuye características físicas tales como rozamiento o rebote.
  • Center: Se determina la posición (x,y,z) de la caja de colisiones respecto del centroide del objeto que se atribuye de esta característica.
  • Size: Se determina la escala de esta caja de colisiones.
unity19

Edit Collider

Observación: Todos los objetos que vayan requerir de ejecutar una acción al colisionar, o interactúen de una u otra manera con otro objeto, deberán tener asociados un determinado Collider

Parte 2 – Programación:

Collision:
Ya habiendo considerado lo necesario a saber en cuanto a la interfaz gráfica del usuario, ahora viene la parte súper divertida, que es programar el comportamiento cuando sucedan las colisiones. Estos comportamientos se deben ejecutar dentro de uno de los dos objetos que van a colisionar. Al hablar de colisiones, en el código se encuentran 3 variantes distintas: cuando los objetos comienzan a colisionar, cuando los objetos se encuentran colisionando o cuando los objetos dejan de colisionar. Cada variante hace referencia a una función que se llamará justamente cuando sucedan estas acciones.

  • void OnCollisionEnter(Collision col): se llama cuando comienza la colisión.
  • void OnCollisionStay(Collision col): se llama durante la colisión.
  • void OnCollisionExit(Collision col): se llama cuando finaliza la colisión.

El parámetro que se le pasa a la función (Collision col) se corresponde con el objeto con el que está colisionando, este objeto que tiene el script.

Veamos un ejemplo: consideremos que cuando colisionan 2 cubos (uno fijo y el otro móvil), el que se está moviendo vuelva a una determinada posición. Para ello vamos a crear un nuevo script dentro del cubo móvil que va a contener lo siguiente:

using UnityEngine;
using System.Collections;
public class DetectCollision : MonoBehaviour {
   void OnCollisionEnter(Collision col){
      this.transform.position = new Vector3(0,-5f,0);
   }
}

Por otro lado, podríamos haber puesto el script dentro del cubo fijo, y queremos que aquel objeto que colisione con él se mueva a una determinada posición, entonces tendremos:

using UnityEngine;
using System.Collections;
public class DetectCollision: MonoBehaviour {
   void OnCollisionEnter(Collision col){
      col.transform.position = new Vector3(0,-5f,0);
   }
}

Observación: El script de la colisión debe estar en solo uno de los objetos que se involucrarán en la misma.
En ambos casos he utilizado la función OnCollisionEnter pues quiero que apenas se produzca la acción, se ejecute el código.
Si hubiese querido que en el momento que la colisión deje de darse se ejecute el código dentro de la función, hubiese utilizado OnCollisionExit.

Trigger:
Todo lo mencionado anteriormente sirve para el caso en que la opción IsTrigger, que mencionamos en la parte de Objetos, está desactivada. Entonces ¿cómo debemos hacer cuando queremos que dos objetos no colisionen fisicamente (no se interpongan uno con el otro) sino que detecten la presencia de uno sobre el otro?.
En principio, tildaremos la opción IsTrigger. A la hora de programar tendremos a nuestra disposición las siguientes 3 variantes que representan las mismas que en el caso de las colisiones normales.

  • void OnTriggerEnter(Collider col): se llama cuando comienza la colisión.
  • void OnTriggerStay(Collider col): se llama durante la colisión.
  • void OnTriggerExit(Collider col): se llama cuando finaliza la colisión.

Una diferencia que podemos notar frente al antes mencionado OnCollisionEnter es que el parámetro que se le pasa a la función en lugar de ser un Collision es un Collider. Éste último representa a la caja de colisión en sí (el Box/Sphere/Mesh Collider que antes colocamos en el objeto), en lugar del objeto que se genera al producirse la colisión.

Veamos un ejemplo de uso del trigger: consideremos que cuando colisionan una bala y un objeto ambos desaparezcan de la escena. Para ello vamos a crear un nuevo script dentro de la bala que contenga lo siguiente:

using UnityEngine;
using System.Collections;
public class DetectHit : MonoBehaviour {
   void OnTriggerEnter(Collision col){
      Destroy(col.gameObject);
      Destroy(this.gameObject);
   }
}

Observación: El evento de trigger solo se ejecuta si uno de los objetos contiene un RigidBody.

Conociendo todos estas variantes, se pueden crear infinitas acciones para cualquier cosa que suceda en una escena, dependiendo de cualquier estado en que los objetos se encuentren.


Y algunas cosas más …

Escenario con plataformas:

Para hacer un escenario al mejor estilo Mario (pudiera ser 2D o 3D) bien sencillo sobre el cual se mueva un personaje e interactúe con plataformas o un determinado suelo, lo que se debe hacer será incluir un RigidBody junto con un BoxCollider al personaje, mientras que a todo lo que sea parte del escenario y sean plataformas o lugares sobre los cuales el personaje no deba caerse al vacío, se le colocará nada más que el BoxCollider.

Una recomendación para lo que serían las plataformas y el suelo, es colocarles un determinado Tag que por ejemplo se llame Terreno. Esto será útil para que a la hora de generar un script sobre nuestro personaje y, por ejemplo, queremos hacer que salte solo cuando está encima de una plataforma, sea cual sea la plataforma, dentro de la función OnCollisionStay preguntemos si el objeto con el cual colisiona tiene asociado el Tag:Terreno y además se presiona por ejemplo la barra espaciadora, entonces el personaje se adquiera una fuerza vertical personaje.AddForce(new Vector3(0,y,0)) siendo y la magnitud de la fuerza que se le quiera aplicar.


A continuación un par de páginas para acentuar o resumir con mejores palabras que las mías, cada una de las cosas detalladas en el post.

Documentación Collider:
http://docs.unity3d.com/ScriptReference/Collider.html

Documentación Collision:
http://docs.unity3d.com/ScriptReference/Collision.html

Y aquí, un tutorial, un poco mas profundo sobre el Colliders en Unity:
http://unity3d.com/learn/tutorials/modules/beginner/physics/colliders

Y aquí doy por finalizado este tema. Si veo que por ahí surgen mas problemáticas que se deban conocer sobre el mismo, iré agregando sus soluciones en este mismo post.

And keep on rolling …

Deja un comentario