Premios y enemigos en Unity.

Un juego sin premios no es nada, pero un juego sin enemigos… un ARCADE sin nadie que te persiga o nadie a quien enfrentarte no tiene sentido! Vamos a incorporar a nuestro juego premios que tendremos que ir recolectando y enemigos que nos perseguirán para acabar con nosotros a los que podremos aniquilar, con un poco, o mucha pericia.

Este post forma parte del tutorial de desarrollo de juegos en Unity. En los post anteriores hemos creado el escenario, el protagonista y puesto la cámara. Si quiere empezar desde aquí puedes bajarte el fichero con el proyecto Unity con todas las modificaciones que hemos hecho por ahora: megafastball-camara.

Los premios

Vamos a utilizar un modelo de los Asset Standard. Se llama PickupPrototype01x01x01, lo encontramos en Standard Assets->Prototyping->Models.

Escogiendo el objeto pickup.

Cogemos el Model y lo arrastramos a la sección Hierarchy, así creamos un objeto nuevo en el juego. Nos aparecera en el centro de nuestro escenario. Podemos desplazarlo si queremos, lo que si que tendríamos que hacer es modificar su eje Y para que no quede, una parte de el, dentro del suelo.

Se muestran las monedas a recolectar por la bola
Esta es la pinta que tendrán los premios en nuestro juego.

Como podéis ver no es que sea el premio más original del mundo, pero es que estamos usando los Assets standard de Unity, así que nos vamos a conformar con tener que recoger monedas con nuestra bola :-). Una vez copiado le cambiamos el nombre a Moneda, y vamos a ver sus propiedades en el Inspector.

Las propiedades del nuevo objeto moneda que acabamos de crear
Propiedades de nuestra moneda.

No se en que país disponen de monedas fucsia, pero yo no he visto ninguna, así que una de las cosas que vamos a hacer cambiarle el material. Mi moneda esta usando el PinkSmooth, lo duplicamos, creando un nuevo material y lo llamamos MaterialMoneda, yo lo arrastro a una carpeta diferente, para no mezclar los assets standard con los que creamos nosotros. Lo dejaré en la carpeta MisPrefabs.

Lo primero que vamos a hacer es cambiar el material. En su Albedo vamos a poner algo mas apropiado a una moneda, en textures tenemos una que se llama SwatchYellowAlbedo, la arrastramos, hacia el cuadradillo Albero de nuestro MaterialMoneda.

Modificamos el Albedo y los colores del material.
Modificaciones en nuestro Material Moneda.

Aparte de cambiar el Albedo también he jugado un poco con los colores, para rebajar el nivel de brillo de la moneda, que podíamos dejar ciego a algún jugador.
Si le damos al Play, veremos como nuestra Bola no puede recoger nuestra moneda, pasa a través de ella. Este no es el comportamiento buscado, tendremos que solucionarlo.

Después de ver el vídeo, hay otro problema, la moneda es demasiado grande, bueno, a mi me lo parece. Así que vamos a ajustarla, ya tendríamos que saber como hacerlo. Tenemos que modificar los valores de Scale, dentro del apartado transform en la sección Inspector de nuestra moneda. Yo lo he dejado a 0.5.

Haciendo que nuestra moneda se pueda recoger.

Para que podamos coger, o interactuar un objeto, este tiene que tener un Collider, y justamente es lo que le falta a la moneda. Vamos a incorporar uno:
Con la moneda seleccionada pulsamos el botón Add Component y seleccionamos: Physics->Collider->Sphere Collider.

Añadimos un rigid body. Add component->Physics->Rigid Body. Desmarcamos la casilla Use Gravity y marcamos la Is Kinematic.

Incorporamos, a nuestra moneda, el script para recogida de tesoros: Recordar que se hace desde el botón Add Component del Inspector de la moneda.

using UnityEngine;
using System.Collections;
public class Premio : MonoBehaviour {
public int value = 10;
public GameObject explosion;
void OnTriggerEnter (Collider other)
{
if (other.gameObject.tag == "Player") {
// explode if specified
if (explosion != null) {
Instantiate (explosion, transform.position, Quaternion.identity);
}
// destroy after collection
Destroy (gameObject);
}
}
}

Lo primero que hacemos es crear dos variables publicas, estas variables son las que veremos en el apartado Inspector y a las que podremos dar valor. Estas dos variables modificaran el comportamiento del Objeto (cuando acabemos el script). Las dos variables creadas són:

  • value: Incrementará el contador del juego en el numero indicado. Por ahora no tenemos contador del juego.
  • explosion: No hemos creado ninguna explosión pero lo haremos en breve. Cuando creemos una empezaremos a ponerlas en todos los objetos que deben explotar, entre ellos nuestras monedas.

La función que hemos programado se llama OnTriggerEvent y se lanza cada vez que el objeto es traspasado con algo, como parámetro recibe el objeto con el que se ha colisionado. Con esta línea: if (other.gameObject.tag == “Player”) Comprobamos si hemos chocado con un objeto que tenga el Tag “Player”. En caso de ser así nuestra moneda se autodestruye, aunque antes, si tiene una explosión, la ejecuta.

Pôdemos ver que nuestra Bola tiene el Tag Player.

Como hemos creado nuestra Bola con un Asset standard de Character, ya nos viene informado con el Tag Player.

Los tags nos pueden servir para dar el mismo comportamiento a diferentes grupos de objetos. Por ejemplo podríamos tener monedas, billetes, y diamantes y darles a todos el tag “tesoro”. Seria una forma de agruparlos para que tuviesen el mismo comportamiento. Es decir, imaginad que tenemos mas de un Player, o un player enemigo, solo tenemos que ponerles a todos el tag Player y podrían recoger monedas.

Ahora ya tenemos nuestra moneda configurada como queremos, bueno, mas adelante trabajaremos un poco más en su script, pero ya podríamos decir que podemos usarla como plantilla, y ya sabemos que las plantillas en Unity son los Prefabs, así que cogemos y arrastramos nuestra moneda de la sección Hierarchy, a la sección Project, dentro de la carpeta Mis Prefabs.

Arrastramos la moneda para crear un Prefab
Creamos un Prefab con nuestro objeto moneda.

Ahora que ya tenemos nuestro Prefab moneda, podemos aprovechar para crear unas cuantas monedas, tan solo tenemos que arrastrar el prefab tantas veces como queramos dentro de la sección hierarchy y distribuir las monedas.

Cualquier cambio que realicemos al PreFab se vera reflejado en todos los objetos de su tipo que hemos creado.

Creamos a los villanos.

Nuestros enemigos, nos van a perseguir, y si nos tocan nos destruirán. La única forma que tenemos de defendernos es hacer que choquen entre ellos. También podríamos hacer que nos roben las monedas, pero no hace falta, es una modificación que dejo al gusto de cada uno.

Para crear nuestro primer enemigo vamos a utilizar el menu creatre de la sección hierarchy, podemos escoger cualquiera de las formas que nos aparecen, en mi caso he escogido un cuadrado, la cápsula también podría ser una buena opción.

Creará un objeto con el nombre de la figura seleccionada, en mi caso Cube, pero se lo he cambiado a enemigo. Igual que hicimos con la moneda vamos a crear un material para el, para ello duplicamos PinkSmoothMaterial, de Standard Assets, y lo copiamos a la carpeta Mis Prefabs, cambiando el nombre a MaterialEnemigo.

Contenido de MisPrefabs después de duplicar el Material.
Duplicamos PinkSmooth, lo copiamos a MisPrefabs y le cambiamos el nombre.

Seleccionamos el objeto recién creado, le cambiamos el nombre a: enemigo, y le añadimos un script que tenemos que crear. Lo hacemos como siempre, desde la sección Inspector pulsamos Add Component y seleccionamos New Script. Este escript es el que le indicará a los enemigos a quien tienen que perseguir. Lo ho he llamado perseguir.

using UnityEngine;
using System.Collections;
public class Perseguir : MonoBehaviour {
public float speed = 5.0f;
public float minDist = 1f;
public Transform target;
// Función de inicialización
void Start () 
{
// Si no tenemos un Target especificado, se perseguira al objeto con el tag Player. 
if (target == null) {
//Buscamos un objeto con el Tag Player.  
if (GameObject.FindWithTag ("Player")!=null)
{       //Si lo encontramos lo situamos como Target. 
target = GameObject.FindWithTag ("Player").GetComponent<Transform>();
}
}
}
// Se le llama en cada frame
void Update () 
{
//Si no tenemos un target no hacemos nada, pa que vamos a movernos. 
if (target == null)
return;
// Mira hacia el target. 
transform.LookAt(target);
//Recupera la distancia que hay desde el objeto al target
float distance = Vector3.Distance(transform.position,target.position);
//Nos movemos hacia el target a la velocidad indicada. 
if(distance > minDist)	
transform.position += transform.forward * speed * Time.deltaTime;	
}

En el script encontramos las dos funciones mas comunes en cualquier Script de Unity: Start() y Update(). La primera se ejecuta cada vez que se crea el objeto, y la segunda en cada Frame. çDefinimos las tres variables que vamos a ver en el editor:

  • speed: la velocidad a la que se mueve el target, definimos 5 como la velocidad por defecto, pero podremos cambiarlo desde el editor.
  • minDist. La distancia a la que se debe acercar el objeto al target, por defecto se va a parar cuando nos toque.
  • target: El objeto al que vamos a seguir, aunque ya vemos en el código que si no le indicamos ninguno el busca un Player al que perseguir.

Vamos a ejecutar nuestro juego a ver como queda y que sucede con el enemigo.

Como vemos nuestro enemigo se ha convertido en una especie de cubo psicopata que nos sigue a todos lados, pero cuando nos alcanza no pasa nada. El siguiente paso es que nuestra bola desaparezca cuando es alcanzada por un cubo. También vamos a realizar otras modificaciones, que lo conviertan en un perseguidor un poco mas espectacular.

Lo primero que tenemos que hacer es darle un rigidbody, ya que ahora mismo pasa a través de los muros, u obstáculos, que vayamos poniendo en el juego.

Incorporamos un rigid body a nuestro enemigo.

Se lo incorporamos desde el botón: add component->physics->Rigid Body. No solo vamos a darle un body para que choque, sino que vamos a hacer que rebote de lo lindo por el escenario. Para eso modificaremos la propiedad Material de su Box Collider y lo pondremos en Bouncy.

Nuestro enemigo va a rebotar!!!

Lo siguiente va a ser crear un script para los enemigos, que detecten cuando colisionan, y que si colisionan con un Player, o con otro enemigo lo destruyan. Seleccionamos al objeto Enemigo, y en su sección Inspector pulsamos Add Component->New Script. Yo he llamado al Damage al Script.

using UnityEngine;
using System.Collections;
public class Damage : MonoBehaviour {
void OnCollisionEnter(Collision other)			
{
//Si chocamos con un Player lo eliminamos a el. 
if (other.gameObject.tag == "Player") {
Destroy (other.gameObject);
}
//Si chocamos con otro enemigo nos eliminanos a nosotros mismos. 
if (other.gameObject.tag == "Enemy") {
Destroy (gameObject);
}
}			
}

El script es casi autoexplicativo. Solo capturamos una función, que es llamada por Unity cuando el Objeto colisiona: OnCollisionEnter. Si lo hace con un objeto de tipo Player (Recordad que nuestra FastBall tiene el tag “Player”) simplemente lo destruye.

Si lo hace con un objeto con el tag “Enemy” se destruye a si mismo. Por ahora esto no va a suceder, para que suceda necesitamos hacer dos cosas: Crear mas enemigos y incorporar el tag Enemy a los enemigos.

Nuestro objeto Enemy ya podría ser considerado una plantilla, así que lo podemos arrastrar hacia la sección Project, dentro de Mis Prefabs y a partir de ahora haremos las modificaciones en el Prefab. La primera modificación va a ser poner el Tag: Enemy.

Incorporando un nuevo Tag.

Después de seleccionar en le menu que queremos un nuevo Tag, lo incorporamos pulsando el botón: + que encontramos en la parte superior derecha. Después de crearlo tan solo tenemos que asignar el tag a nuestro Prefab de Enemigo.

El enemigo con el Tag Enemy aplicado.

Ya tenemos nuestra plantilla, o Prefab de enemigo creado, arrastremos unos cuantos al escenario, yo he arrastrado cuatro que he puesto en las cuatro esquinas del escenario. Ahhh, y los he situado unos cuatro metros por encima del suelo, me gusta que vayan rebotando por el escenario.

Podemos ver como nos persiguen cuatro enemigos, pero no es muy complicado desacerse de ellos, cuando los hacemos chocar, desaparecen!

¿Que hemos aprendido?

Muchas Cosas!!!! Hemos incorporado tres Scripts, el de recogida de tesoros, el de los enemigos que hace que nos sigan, y el que hace que los enemigos desaparezcan al chocar o eliminen al protagonista. Hemos visto como trabajar con Prefabs para crear diversos objetos y nuestro juego empieza a tomar forma. Ya tenemos a un protagonista, que recorre el escenario recogiendo sus premios y que muere cuando un enemigo le toca, y por si fuera poco, le hemos dado una forma de eliminar a los enemigos.

¿Que le falta a nuestro juego?

Muchísimas cosas, le falta un contador de puntos, un gestor de niveles, música, efectos, un escenario mas resulton… En el proximo Post vamos a intentar maquillar un poco el juego, para que con pocos cambios empiece a tener mejor pinta. Para eso lo mejor sera incorporar un poco de música, cambiar el skybox, crear animaciones para las explosiones… y hacer que el juego acabe si nuestra bola cae al abismo!

Next: Música y explosiones en nuestro juego de Unity.

Comentarios.