Post on 17-May-2018
Cómo hacer un juego en 60 minutos
Taller Unity3D
I Jornadas sobre Videojuegos
Máster de Videojuegos – GUEIM
Universidad Complutense de Madrid – Diciembre 2010
Fernando Matarrubia – taller.unity@gmail.com
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 2
Contenido
1. Concepto .............................................................................................................................................. 3
2. Creación de un proyecto nuevo ........................................................................................................... 4
3. Creación de escenas ........................................................................................................................... 5
4. Escenario ............................................................................................................................................. 6
4.1. Plataformas y objetivo ................................................................................................................. 6
4.2. Iluminación .................................................................................................................................. 8
5. Jugador ................................................................................................................................................ 9
6. Elementos de juego: Prefabs ............................................................................................................. 11
6.1. Objeto de juego: Proyectil ......................................................................................................... 11
6.2. Objeto de juego: Enemigo ......................................................................................................... 12
7. Etiquetado de objetos ........................................................................................................................ 13
8. Scripting ............................................................................................................................................. 14
8.1. Muerte por caída ....................................................................................................................... 14
8.2. Disparando ................................................................................................................................ 15
8.3. Spawn de enemigos .................................................................................................................. 16
8.4. Liberar memoria ........................................................................................................................ 17
8.5. “Un toque mata” ........................................................................................................................ 18
8.6. Llegando a la meta .................................................................................................................... 19
8.7. ¡Bonus Track! ............................................................................................................................ 21
9. Cielo, materiales y texturas ................................................................................................................ 22
9.1. Mirando al horizonte .................................................................................................................. 22
9.2. El suelo que pisas ..................................................................................................................... 22
9.3. Enemigos con carisma .............................................................................................................. 24
9.4. Toque final ................................................................................................................................. 24
9.5. ¡Bonus track! ............................................................................................................................. 25
10. ¡Música Maestro! ........................................................................................................................... 25
11. Build Multiplataforma ..................................................................................................................... 26
12. Bibliografía, Referencias y Materiales ........................................................................................... 27
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 3
1. Concepto ¿Qué juego vamos a hacer? ¿Cuáles van a ser nuestros personajes? ¿Y nuestro argumento? ¿Y la
jugabilidad? ¿Y las mecánicas?
Debido a la filosofía del taller; aprender lo máximo posible de Unity en un tiempo muy limitado, no nos
podemos extender demasiado en esta parte esencial en la creación de todo videojuego.
Lo que vamos a hacer va a ser un FPS/Plataformas muy básico, en el que nuestro objetivo será llegar a
una determinada parte del mapa sorteando diversas esferas que caen sobre nosotros.
La esencia del concepto se define con el siguiente dibujo:
Ilustración 1. Concepto de juego
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 4
2. Creación de un proyecto nuevo
El primer paso es crear un nuevo proyecto de Unity:
Ruta: File – New Project
Ilustración 2. Crear nuevo proyecto
En el cuadro de diálogo que aparece, elegimos las siguientes tres opciones:
Ilustración 3. Importación de recursos
Esto importará algunos recursos (assets) estándar proporcionados por el equipo de Unity, que nos serán
muy útiles a la hora de ahorrarnos trabajo realizando nuestro juego.
En los equipos del laboratorio, únicamente el directorio C:\hlocal tiene permisos de escritura. Por
ello, aquellos que no tengan equipo propio están obligados a crear su proyecto en dicha ruta.
Es importante descomprimir dentro de la ruta C:\hlocal\[proyecto]\Assets el archivo
Material.zip suministrado antes del taller. Se crearán las carpetas Sounds e Images.
Una vez hecho esto, estamos listos para comenzar.
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 5
3. Creación de escenas
Unity funciona mediante escenas. Una escena es un “nivel” de nuestro juego. Todos sus elementos son
privados, y no se pueden usar fuera de ella. En un juego cualquiera hecho en Unity, podríamos tener una
escena para el menú principal, otra para un tutorial, otra para cada nivel, y una última para el vídeo final
de juego.
Cuando se carga una escena, se llevan a memoria todos sus elementos. Al ser descargada, se desaloja
de memoria todo aquello que la escena estaba utilizando. Existen mecanismos para hacer desalojos
selectivos, de manera que las escenas puedan comunicarse entre ellas.
En nuestro caso sólo necesitaremos una escena. Para crearla, bastará con guardar la escena actual
(vacía):
- Ruta: File – Save Scene
- Nombre: game.unity
Ilustración 4. Escena creada en nuestro proyecto
Ahora debemos añadir la escena a los Build Settings del proyecto para poder ser referenciada desde
código (es decir, para que el proyecto sepa que la escena “existe”):
- Ruta: File – Build Settings – Add Current (debido a que queremos añadir la escena actual)
Ilustración 5. Escena añadida en Build Settings
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 6
4. Escenario
4.1. Plataformas y objetivo
Es hora de construir el núcleo de nuestro juego. Tal y como se puede ver en la ilustración del concepto, el
escenario contará con 4 bloques flotantes que harán de suelo y uno situado sobre el más alejado del
jugador, que será el que se tendrá que alcanzar para finalizar el juego. Cada uno de los bloques será un
GameObject con sus propios componentes Mesh Filter, Box Collider y Mesh
Renderer, que se configurán por defecto.
Numeraremos los bloques como se ve en la siguiente captura:
Ilustración 6. Numeración de bloques del escenario
Para crearlos, utilizaremos cubos re-escalados. Para añadir un cubo a la escena bastará con desplegar la
opción GameObject – Create Other – Cube de la barra de herramientas:
Ilustración 7. Creación de un cubo
Podéis ir alternando las perspectivas haciendo click en las diferentes flechas del siguiente icono. Aparte,
podéis mover el punto de vista con Click Central y rotarlo con Alt + Click Izquierdo:
Ilustración 8. Eje de coordenadas y perspectiva
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 7
A cada bloque lo llamaremos BloqueX, donde X será el número que le corresponda. El bloque número
5 se llamará Objetivo. A continuación se muestran la matriz de transformación que tendrá que tener
cada bloque para conseguir el escenario de la Ilustración 7.
Nombre Matriz de Transformación
Bloque1
Bloque2
Bloque3
Bloque4
Objetivo
Tabla 1. Matrices de transformación
Para poder mover y rotar nuestro escenario como un solo bloque, bastará con crear un GameObject
vacío mediante: GameObject – CreateEmpty al cual llamaremos Escenario y arrastrar dentro de él
todos nuestros objetos. Antes de hacerlo, tenemos que estar seguros de que nuestro objeto vacío se
encuentra en la posición (0, 0, 0) y no tiene aplicada ninguna rotación, ya que sus hijos lo tomarán
como origen de coordenadas. Para que un bloque sea hijo de nuestro objeto Escenario, dentro de la
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 8
jerarquía de nuestra escena (Hierarchy) hacemos click en un bloque cualquiera y sin soltar lo arrastramos
encima del nombre de nuestro GameObject vacío. En la siguiente captura se puede ver el momento
inmediatamente anterior de hacer a Bloque1 hijo de Escenario.
Ilustración 9. Jerarquía del escenario
Ahora podremos mover el objeto Escenario, y veremos cómo se mueven todos los bloques. Si
queremos duplicar nuestra estructura, bastará con pulsar Botón Derecho – Duplicate. Se creará otro
objeto Escenario, cuyos hijos serán los mismos que los del objeto original.
4.2. Iluminación
Para iluminar la escena crearemos una luz direccional. Este tipo de luces iluminan en una dirección dada
de forma uniforme. De esta forma, no importa en qué posición la pongamos.
- Ruta: GameObject – Create Other – Directional Light
- La renombramos como Foco
Ilustración 10. Atributos de la luz direccional
Si el usuario quiere, podrá incorporar el foco de luz al GameObject Escenario para tener más
organizada su escena.
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 9
5. Jugador ¡Llega el momento del movimiento! Una vez tenemos nuestro escenario creado nos hace falta un jugador
a quién controlar. Este personaje jugable será también un GameObject pre-configurado por el equipo de
Unity. Sus componentes configuran la funcionalidad completa de un PJ en primera persona.
Para añadirlo a nuestra escena bastará con que arrastremos a nuestra ventana de Editor desde nuestro
Monitor de Recursos, aquél situado en la ruta: Standard Assets – Character Controllers – First Person
Controller
Ilustración 11. Ruta de nuestro recurso Jugador
Allí donde lo hayamos arrastrado aparecerá una cápsula (nosotros mismos). Aparte, en la jerarquía de
nuestra escena, se mostrará el GameObject con el nombre First Person Controller en azul,
lo renombramos a Player.
Ilustración 12. Nuestro héroe
Su matriz de transformación deberá ser la siguiente:
Ilustración 13. Posición inicial de nuestro héroe
Vemos que dentro tiene otros GameObjects:
Ilustración 14. GameObjects de nuestro héroe
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 10
Cada uno de ellos con sus componentes:
Player Graphics Main Camera
Tabla 2. Componentes de nuestro héroe
¡Por fin llegó el momento de pulsar el Play!
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 11
6. Elementos de juego: Prefabs Como hemos dicho antes, cada escena tiene sus propios objetos. Estos objetos son privados a ella, y no
pueden ser utilizados en otra escena. Pero entonces ¿Qué pasa si yo me creo un enemigo y quiero
usarlo en dos escenas diferentes? ¿Tengo que hacerlo dos veces?
Evidentemente no, para ello, Unity cuenta con los Prefab.
Un prefab es un objeto “prefabricado” persistente en disco, y que se guarda en nuestra jerarquía de
proyecto. Puede ser instanciado tantas veces como queramos. Sus instancias, a no ser que se rompa la
conexión con el prefab, tendrán todos y cada uno de los componentes de su objeto padre, y cambiarán
conforme lo haga éste. Podemos saber si un objeto es un prefab porque su nombre dentro de la jerarquía
de escena está coloreado en Azul.
Ilustración 15. Nuestro First Person Controller está enlazado con su prefab
Si realizamos algún cambio, sabremos que se está perdiendo la conexión con el objeto raíz debido a que
aparece el siguiente diálogo:
Ilustración 16. Perdiendo conexión con Prefab
6.1. Objeto de juego: Proyectil
A continuación vamos a crear un prefab que será la munición que podremos disparar posteriormente.
Para ello, seguimos los siguientes pasos:
- Creamos un cubo: GameObject – Create Other – Cube
Ilustración 17. Matriz de transformación de nuestro prefab munición
- Le añadimos un componente Rigidbody (comportamiento físico realista). Con el cubo
seleccionado: Component – Physics – Rigidbody
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 12
- En nuestra jerarquía de proyecto: Botón Derecto – Create – Prefab
- Lo renombramos como Bullet
- (Opcional) En nuestra jerarquía de proyecto creamos una carpeta Prefabs: Botón
derecho – Create – Folder. En ella guardaremos nuestro prefab, y los que hagamos
posteriormente.
- Arrastramos el cubo desde nuestra jerarquía de escena, hasta el nuevo prefab que
acabamos de crear. Su icono cambiara de ser un cubo gris (vacío), a ser un cubo azul
Ilustración 18. Creación de un prefab
- En este punto podemos borrar el cubo de nuestra escena. (Si lo situáis un poco por delante
del jugador y dais al , veréis como el cubo cae, siendo afectado por la
gravedad).
6.2. Objeto de juego: Enemigo
De igual forma que con el prefab anterior, ahora crearemos uno que será nuestro enemigo mortal (^_^).
Para ello seguimos los siguientes pasos:
- Creamos una esfera: GameObject – Create Other – Sphere
Ilustración 19. Matriz de transformación de nuestro prefab enemigo
- Le añadimos un componente Rigidbody (comportamiento físico realista). Con la esfera
seleccionada: Component – Physics – Rigidbody
- En el componente Sphere Collider, configuramos el Material como Bouncy (¡bota!)
(si no aparecen los materiales, es que no se han importado al crear el proyecto. Ver
Apartado 2: Creación de un Proyecto Nuevo)
Ilustración 20. Bouncy Material para nuestro enemigo
- En nuestra jerarquía de proyecto: Botón Derecto – Create – Prefab
- Lo renombramos como Enemy
- (Opcional) Si teníamos la carpeta Prefab, lo arrastramos dentro
- Arrastramos la esfera desde nuestra jerarquía de escena, hasta el nuevo prefab que
acabamos de crear. De nuevo cambiará su icono.
- En este punto podemos borrar la esfera de nuestra escena. (Si la situáis un poco por delante
del jugador y dais al , veréis como el cae y rebota en el suelo)
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 13
7. Etiquetado de objetos Ahora que ya tenemos los objetos principales de nuestro juego creados, tenemos que organizarlos. Si
queremos acceder a un GameObject desde código, podemos buscarlo mediante su nombre, o mediante
su etiqueta. Nosotros utilizaremos etiquetas, ya que es más cómodo debido al número de enemigos que
tendremos.
Unity cuenta con un sistema de etiquetado que el usuario puede configurar a su antojo. A continuación
vamos a establecer y a asignar los nombres de las etiquetas que usaremos en nuestro humilde AAA.
En primer lugar, accedemos al Tag Manager desde Edit – Project Settings - Tags. Para ver las etiquetas
de nuestro proyecto necesitamos desplegar el campo Tags. Tendremos que añadir las etiquetas de la
siguiente ilustración:
Ilustración 21. Etiquetas de nuestro juego
Una vez estén añadidas, tenemos que asignarlas a nuestros objetos.
- Etiqueta bullet: Prefab Bullet
- Etiqueta enemy: Prefab Enemy
- Etiqueta player: GameObject de escena Player
- Etiqueta target: GameObject de escena Objetivo
Para asignarla, tendremos que tener el objeto seleccionado, y bastará con elegirla en la lista desplegable
que se encuentra justo encima de la matriz de la transformación del mismo:
Ilustración 22. Tag player
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 14
8. Scripting
En este apartado vamos a insuflar vida a nuestro juego.
Unity funciona con Mono, una implementación OpenSource del Framework .NET. Por ello, podemos
escribir nuestro código en Javascript, C# o Boo. En el taller vamos a utilizar Javascript debido a que es
algo más “inmediato” que los otros dos.
8.1. Muerte por caída
Lo primero que vamos a hacer será que nuestro jugador muera al caer al vacío. Para ello tendremos que
crear un script que implemente esa funcionalidad, y añadírselo como componente a nuestro objeto
jugador.
- (Por organización) En nuestra jerarquía de proyecto: Botón derecho – Create – Folder
- La renombramos como Scripts
- En nuestra nueva carpeta: Botón derecho – Create – JavaScript
- Lo renombramos como Die
- Escribimos el siguiente código:
function Update () {
if (transform.position.y <=-30){
Dead();
}
}
function Dead(){
Application.LoadLevel("game");
} Código 1. Muerte del jugador
- Arrastramos el script sobre el GameObject Player de nuestra escena:
Ilustración 23. Componente de tipo Script: Die
El código simplemente reinicia el nivel cuando la posición vertical del jugador es igual o inferior a -30, es
decir, cuando el jugador ha caído al vacío.
El método Update() se ejecuta una vez por frame, en él incluimos la funcionalidad. Con
transform.position.y, nos referimos a la posición en el eje vertical de nuestro objeto. Al ser el
script un componente de nuestro jugador, la propia semántica de Unity permite referirse a sus otros
componentes con palabras clave.
En la función Dead(), la cual hemos creado nosotros mismos (no es reservada por Unity), simplemente
cargamos el nivel llamado game. Para que ésto pueda hacerse en tiempo de ejecución es necesario
haber añadido el nivel en las Build Settings del proyecto (ver Apartado 3: Creación de escenas). El
resultado es un reinicio inmediato del nivel, lo cual elimina cualquier progresión que pudiéramos haber
hecho.
¡Probad la caída!
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 15
8.2. Disparando
¡Por fin algo interesante! Vamos a hacer que nuestro héroe dispare cubos extra-resistentes-anti-
enemigos.
Para ello, tendremos que añadir un script a nuestro jugador que implemente dicha funcionalidad. Dicho
script será un componente más de nuestro GameObject Player:
- En nuestra carpeta Scripts: Botón derecho – Create – JavaScript
- Lo renombramos como Shoot
- Escribimos el siguiente código:
public var bullet : Rigidbody;
public var speed = 5;
function Update () {
if (Input.GetButtonDown("Fire1")){
var instantiatedProjectile : Rigidbody = Instantiate(bullet,
transform.position, transform.rotation);
instantiatedProjectile.velocity =
transform.TransformDirection(Vector3(0,0,speed));
Physics.IgnoreCollision(instantiatedProjectile.collider,
transform.root.collider);
}
} Código 2. Disparo
- Arrastramos el script sobre el GameObject MainCamera dentro de nuestro Player.
Este código instancia el objeto bullet en la posición y rotación del GameObject del cual forma parte, y
le imprime una velocidad inicial con valor speed en la dirección Z (hacia delante) local.
bullet y speed son variables públicas, lo cual significa que son visibles desde la jerarquía de
componentes del objeto, y por tanto se les puede dar un valor sin “tocar código”:
Ilustración 24. Variables públicas del script Shoot
Con Input.GetButtonDown leemos de la entrada cuándo se ha pulsado el botón mapeado con el
nombre Fire1. Para ver el mapeo de teclas que utiliza Unity debemos ir a Edit – Project Settings –
Input – y desplegar el elemento Axes. En este caso, detectamos cuándo el usuario pulsa el botón
izquierdo del ratón o la tecla Ctrl.
Cuando el jugador lo pulsa, se instancia con Instantiate el objeto público bullet que le
hayamos pasado desde fuera, y se configura su atributo velocity con el valor speed, únicamente
en el eje Z.
Physics.IgnoreCollision ignora las posibles colisiones existentes entre el nuevo objeto
instanciado y nosotros mismos, de manera que no pueda suceder por ejemplo que disparemos algo y se
quede “dentro” de nosotros por colisionar con la pared interior de nuestro controlador de colisión.
¡Queda un último paso! Configurar las variables públicas de nuestro script, para ello:
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 16
- Arrastramos nuestro prefab bullet en el campo bullet del script
- Ponemos un valor 15 a speed (podéis poner lo que queráis e ir probando)
Ilustración 25. Variables públicas configuradas
¡A disparar!
8.3. Spawn de enemigos
Éste es quizá el punto más importante de nuestro juego. ¿Cuándo, cómo y dónde generamos a nuestros
enemigos? Dentro de nuestro escenario, crearemos un GameObject vacío al cual añadiremos un script.
Dicho script tomará la posición del GameObject y con algunos sencillos cálculos instanciará los enemigos
con una frecuencia establecida por el usuario, en posición (tanto horizontal como vertical) variable, y con
una velocidad inicial (sólo vertical) que también será diferente en cada uno de ellos.
Para ello:
- Creamos un GameObject vacío: GameObject – Create Empty
- Lo renombramos a SpawnEnemies
Ilustración 26. Matriz de transformación de SpawnEnemies
- En nuestra carpeta Scripts: Botón derecho – Create – JavaScript
- Lo renombramos como Enemies
- Escribimos el siguiente código:
public var enemy : Rigidbody;
private var tick : float = 0;
public var speed : float = 5;
public var paso : float = 1;
function Update () {
tick+= Time.deltaTime;
speed = Random.Range(0.0f, 5.0f);
offsetZ = Random.Range(-4.0f, 4.0f);
offsetY = Random.Range(-3.0f, 3.0f);
if (tick>=paso){
tick = 0;
var position : Vector3 =
new Vector3(transform.position.x,
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 17
transform.position.y+offsetY,
transform.position.z+offsetZ);
var instantiatedProjectile : Rigidbody =
Instantiate(enemy, position, transform.rotation);
instantiatedProjectile.velocity =
transform.TransformDirection(Vector3(0,-speed,0));
}
} Código 3. Spawn de enemigos
- Configuramos las variables públicas como se ve en la siguiente captura:
Ilustración 27. Variables públicas del spawn de enemigos
Podemos ver que este código es bastante similar al de la instanciación de las balas disparadas por
nuestro personaje (ver Apartado 8.2: Disparando). La principal diferencia es la posición en la cual se
crean nuestros enemigos. Para dar un comportamiento emergente a nuestro juego, hacemos que dicha
posición varíe dentro de unos límites respecto a la posición de nuestro GameObject SpawnEnemies.
En nuestro caso (-3, 3) para la posición vertical, y (-4,4) para la posición vertical.
Aparte de esto, controlamos la frecuencia de instanciación de los enemigos con la variable tick. Dicha
variable, que inicialmente es cero, va almacenando el sumatorio del tiempo de ejecución del frame N-1
(Time.deltaTime). De esta forma, podemos llevar la cuenta del tiempo transcurrido en un
determinado momento del juego, independientemente de la máquina que tengamos (más o menos
potente). Controlando el límite superior al que puede llegar tick mediante la variable pública paso, el
usuario puede configurar desde fuera cuántos segundos tienen que transcurrir entre la aparición de los
diferentes enemigos. En la Ilustración 26 se muestra un valor ajustado de la variable paso.
¡Avalancha!
8.4. Liberar memoria
Es importante no cargar la escena de demasiadas instancias de un objeto. Para ello, podemos configurar
éstos para se destruyan automáticamente después de X segundos.
Para ello, tendremos que crear un nuevo script y añadirlo como componente al prefab de nuestros objetos
(bullet y enemy):
- En nuestra carpeta Scripts: Botón derecho – Create – JavaScript
- Lo renombramos como SelfDestroy
- Escribimos el siguiente código:
public var waitTime : float = 10;
function Start () {
Destroy(gameObject, waitTime);
} Código 4. Autodestrucción
- Arrastramos el script sobre los prefabs bullet y enemy.
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 18
- Para waitTime configuramos los siguientes valores:
bullet
enemy
Tabla 3. Valores en segundos para la autodestrucción de objetos
Este script es sencillo. Simplemente se llama a Destroy sobre nosotros mismos, con un retardo de
waitSeconds segundos. Una vez transcurrido ese tiempo, el objeto se destruye.
Es importante observar que esta vez no incluimos nuestra funcionalidad en el método Update, sino que lo
hacemos en el método Start() perteneciente al API de Unity, y cuyo contenido se ejecuta al ser
instanciado el GameObject que tiene el componente script añadido.
8.5. “Un toque mata”
En esta sección vamos a complicar la lógica del juego. Lo que queremos conseguir es que el jugador
muera cada vez que sea golpeado por un enemigo. Aparte, para facilitarte un poco la tarea, también
realizaremos un pequeño script que destruya una esfera al entrar en contacto con uno de nuestros
mortíferos proyectiles.
Primero, añadimos la amenaza enemiga:
- En nuestra carpeta Scripts: Botón derecho – Create – JavaScript
- Lo renombramos como Kill
- Escribimos el siguiente código:
function OnCollisionEnter(collision: Collision) {
if (collision.gameObject.tag=="player"){
collision.transform.SendMessage("Dead");
}
} Código 5. Autodestrucción
- Arrastramos el script sobre el prefab enemy.
La función OnCollisionEnter es ejecutada por el GameObject correspondiente siempre que su
controlador de colisión entra en contacto con otro. Como parámetro envía el controlador de colisión contra
el que se ha chocado. En este caso seleccionamos aquella colisión que sea con el jugador, es decir,
contra un gameObject cuyo tag sea player (ver Apartado 7: Etiquetado de Objetos), y enviamos un
mensaje al mismo, con el nombre de la función a ejecutar (ver Apartado 8.1: Muerte por caída). De esta
forma, cada vez que una esfera-asesina entre en contacto con nuestro héroe, éste llamará a su función
Dead() y se reiniciará el nivel.
Ahora es momento de hacer que nuestros cubos sirvan para algo:
- En nuestra carpeta Scripts: Botón derecho – Create – JavaScript
- Lo renombramos como Attack
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 19
- Escribimos el siguiente código:
public var destroyOnCollision : boolean = true;
function OnCollisionEnter(collision : Collision) {
if (destroyOnCollision) Destroy (gameObject);
if (collision.gameObject.tag == "enemy"){
Destroy(collision.gameObject);
}
} Código 6. Autodestrucción
- Arrastramos el script sobre el prefab bullet.
Este código funciona de manera similar al anterior. Para todas las colisiones de nuestros bullet, se
busca aquellas que ocurran contra gameObjects cuyo tag sea enemy (ver Apartado 7: Etiquetado de
Objetos), en cuyo caso el objeto destino es destruido. Con una variable pública
destroyOnCollision podemos establecer si queremos que nuestro bullet se destruya al
entrar en contacto con algún objeto (no sólo enemigos) o no.
8.6. Llegando a la meta
¡Ya era hora de ponerle fin al juego! En este apartado controlaremos cuándo el jugador toca el
GameObject Objetivo, y finalizaremos nuestro breve periplo.
Para ello en primer lugar crearemos una imagen que será mostrada sobre la pantalla cuando ocurra la
colisión entre nuestro jugador y el Objetivo:
- Debemos crear una GUITexture: GameObject – Create Other – GUITexture
- Lo renombramos como Finish
Ilustración 28. Configuración de nuestro GUITexture
Los atributos arriba descritos son aplicables a la imagen finish.png (suministrada junto a este tutorial). Es
importante que el componente GUITexture esté desactivado de inicio (marcado en verde) para que no
sea visible e interfiera con la jugabilidad.
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 20
Ahora tendremos que crear el script con el cual mostraremos la imagen una vez hayamos llegado al final
del nivel. También permitiremos reiniciarlo pulsado una determinada tecla:
- En nuestra carpeta Scripts: Botón derecho – Create – JavaScript
- Lo renombramos como Finish
- Escribimos el siguiente código:
private var finished : boolean = false;
public var finishedText : GUITexture;
function Start(){
finishedText.enabled = false;
Time.timeScale = 1.0;
}
function Update () {
if (Input.GetKeyDown(KeyCode.Escape) && finished){
Application.LoadLevel("game");
}
}
function OnControllerColliderHit(hit: ControllerColliderHit){
if (hit.collider.gameObject.tag=="target"){
finished = true;
finishedText.enabled = true;
Time.timeScale = 0.0;
}
} Código 7. Final de nivel
- Arrastramos el script sobre el GameObject Player
- Arrastramos nuestro GUITexture Finish, al campo Finished Text del componente
script
En primer lugar, tenemos una variable pública correspondiente al componente GUITexture de nuestro
objeto Finish. Gracias a dicha variable, podremos hacer visible la imagen cuando nuestro
CharacterController colisione con el GameObject Objetivo. Para ello, usamos la función
OnControllerColliderHit y gestionamos el caso en el que la colisión sucede contra un objeto
cuyo tag es target. En ese caso ponemos a true un flag finished, activamos nuestra imagen, y
paramos el tiempo. Dentro del método Update, controlamos que cuando el flag finished está
activado y el jugador pulsa la tecla escape, el nivel se reinicie.
El método Start() desactiva la visibilidad de la imagen y reconfigura el tiempo a su velocidad normal.
Esto se realiza por seguridad, para que en ningún caso se muestre la imagen cuando comience el juego
ni el tiempo esté parado.
“Ya me lo he pasao”
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 21
8.7. ¡Bonus Track!
A continuación se muestra el código de un script que permite al jugador parar el tiempo pulsando la tecla
P. Hay que tener en cuenta que si se para el tiempo, también el jugador deja de moverse . También se
muestra una re-implementación de la función Shoot, que emula el funcionamiento de una metralleta,
cuya cadencia se puede controlar mediante una variable pública y que ofrece la posibilidad de disparar
proyectiles con una velocidad inicial aleatoria. Por último, con una simple línea de código, podemos hacer
un GameObject rote sobre un eje vertical
function Update () {
if (Input.GetKeyDown (KeyCode.P)) {
Time.timeScale = 1.0-Time.timeScale;
Time.fixedDeltaTime = 0.02 * Time.timeScale;
}
} Código 8. Parar el tiempo
public var bullet : Rigidbody;
public var speed : float = 5.0f;
public var paso : float = 1.0f;
public var randomSpeed : boolean = false;
private var tick : float = 0.0f;
function Update () {
tick+=Time.deltaTime;
if (randomSpeed) speed = Random.Range(0.0f, 20.0f);
if (tick>=paso){
tick = 0;
if (Input.GetButton("Fire1")){
var instantiatedProjectile : Rigidbody =
Instantiate(bullet, transform.position, transform.rotation);
instantiatedProjectile.velocity =
transform.TransformDirection(Vector3(0,0,speed));
Physics.IgnoreCollision(instantiatedProjectile.collider,
transform.root.collider);
}
}
} Código 9. RepeatedShoot
public var rotAmount : float = 30;
function Update () {
transform.Rotate(new Vector3(0, rotAmount,0));
} Código 10. Rotación continua
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 22
9. Cielo, materiales y texturas En esta sección vamos a darle un poco de color a nuestro juego. En primer lugar configuraremos un cielo
para la escena, de manera que nuestro espacio sea un poco más “artístico”. Posteriormente, crearemos
materiales de diferentes tipos para las plataformas del escenario, los enemigos, y el objetivo.
9.1. Mirando al horizonte
Para configurar nuestro cielo bastará con hacerlo en la configuración de Renderizado del proyecto:
- Ruta: Edit – Render Settings – Skybox Material
- Elegimos uno de entre la lista de disponbles
Ilustración 29. Elección del skybox
9.2. El suelo que pisas
A continuación crearemos un material con relieve (Bump) para el suelo:
- En nuestra jerarquía de proyecto: Botón derecho - Create – Folder
- Lo renombramos como Materials
- Sobre nuestra nueva carpeta: Botón derecho – Create – Material
- Lo renombramos como GreyStone
- Lo configuramos como BumpedDiffuse (marcado en verde en la imagen)
- Le configuramos el color que queramos (preferiblemente gris) haciendo click en el cuadro
blanco de Main Color
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 23
Ilustración 30. Material de piedra para nuestro suelo
Para poder configurar el Normalmap tal y como se ve en la Ilustración 29, debemos generarlo antes en
nuestra jerarquía de proyecto:
- Dentro de nuestra carpeta Images (ver Apartado 2: Creación de un proyecto nuevo)
hacemos click sobre la imagen stone-bumpmap.jpg
- En el Texture Importer, configuramos la imagen como Normal Map y hacemos click en
Apply
Ilustración 31. Texture Importer: Normal Map
- Arrastramos nuestra imagen al canal Normalmap de nuestro material GreyStone
(ver Ilustración 29)
Una vez hecho esto, bastará con arrastrar nuestro material directamente a los objetos de nuestra escena
que queramos que lo usen. Es indiferente hacerlo en la jerarquía de la escena, o en la representación
gráfica de los mismos. Ahora deberíamos tener más o menos el siguiente resultado:
Ilustración 32. Suelo de piedra
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 24
9.3. Enemigos con carisma
De igual forma que con el suelo, crearemos una textura para los enemigos. En este caso será algo más
simple:
- Sobre nuestra carpeta Materials: Botón derecho – Create – Material
- Lo renombramos como WaterMelon
- Lo configuramos como Diffuse (por defecto)
- Arrastramos desde nuestra carpeta Images la imagen: watermelon.jpg al canal Base de
nuestro material
- Configuramos los valores de Tiling y Offset tal y como se ve en la imagen.
Ilustración 33. Material para nuestros enemigos
- Arrastramos el material a nuestro prefab Enemy
¡Socorro, Sandías!
9.4. Toque final
En este último material simplemente veremos cómo modificar la transparencia de un objeto:
- Sobre nuestra carpeta Materials: Botón derecho – Create – Material
- Lo renombramos como Transparent
- Lo configuramos como Transparent/Diffuse
- En el cuadro de color, elegimos el que queramos, y modificamos la transparencia (canal A) a
nuestro gusto
Ilustración 34. Color y transparencia
- Arrastramos el material a nuestro GameObject de escena Objetivo
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 25
9.5. ¡Bonus track!
Entre el material extra que se ha suministrado hay una imagen llamada orange-bumpmap.png, la cual
se puede utilizar para crear un Material de tipo BumpedDiffuse, con MainColor naranja, y
posteriormente aplicárselo al prefab enemy, consiguiendo así la textura de una naranja. Se deja a
elección del usuario el implementar esta “asombrosa” funcionalidad. . También está disponible una
textura llamada dominoPiece.png, por si alguien quiere modificar las dimensiones de su prefab
bullet y aplicarle esta textura, de manera que dispare fichas de dominó-asesinas. (Quizás podría
combinarse con el Script de rotación del Bonus Track de Scripting).
10. ¡Música Maestro! En este último punto vamos a añadir una melodía de fondo que vaya incrementando su volumen según
nos acerquemos a la fuente del sonido.
Para ello:
- Tenemos que tener una carpeta Sounds con el track: BSO_GrimFandango.mp3 dentro
(ver Apartado 2: Creación de un proyecto nuevo)
- Arrastramos el track a nuestro GameObject Objetivo. Se creará un componente
AudioSource.
Ilustración 35. Componente AudioSource
- Creamos un script llamado Sound en nuestra carpeta Scripts
function Start() {
audio.Play();
} Código 11. Activando música
- Arrastramos el script a nuestro GameObject Objetivo
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 26
11. Build Multiplataforma Hacer el Build es el último paso de nuestro juego. Con ello, construimos un ejecutable que puede correr
en cualquier máquina para la que haya sido realizado.
El proceso es bastante simple:
- Ruta: File – Build Settings
- Seleccionamos la plataforma para la cual queremos hacer el build
- Elegimos el Target (sólo disponibles en algunas plataformas)
- Pulsamos el botón Build
- Elegimos la ruta donde se guardará nuestro ejecutable. Preferiblemente que sea una
carpeta, ya que al mismo nivel del ejecutable se crean más archivos con los recursos del
proyecto, dependencias, etc…
Ilustración 36. Pantalla de Build
En el caso
Con la versión gratuita de Unity sólo podremos realizar Builds para Navegador Web, Windows y MAC.
Para el caso de un Build para navegador, se crea un archivo con extensión *.unity3d, y un
*.html que lleva embebido con el código HTML necesario para la visualización web de nuestro juego.
Bastará con abrir el HTML en una máquina que tenga instalo el plugin de visualización correspondiente
(Unity Web Browser Plugin) y…
¡A jugar!
Cómo hacer un juego en 60 minutos - I Jornadas sobre Videojuegos MDV/GUEIM - UCM 27
12. Bibliografía, Referencias y Materiales
1. Will Goldstone. Unity Game Development Essentials.
https://www.packtpub.com/unity-game-development-essentials/book
2. Graham McAllister. GUI Essentials (Introduction Tutorial 1)
http://download.unity3d.com/support/Tutorials/1%20-%20GUI%20Essentials.pdf
3. Graham McAllister. Introduction To Scripting With Unity (Introduction Tutorial 2).
http://download.unity3d.com/support/Tutorials/2%20-%20Scripting%20Tutorial.pdf
4. Graham McAllister . Unity First Person Shooter Tutorial
http://unity3d.com/support/resources/tutorials/fpstutorial.html
5. Unity Basics
http://unity3d.com/support/documentation/Manual/Unity%20Basics.html
6. Official Scripting Documentation
http://unity3d.com/support/documentation/ScriptReference/index.html
7. Official Tutorials
http://unity3d.com/support/resources/tutorials/
8. Official Community
http://unity3d.com/support/community
9. UnitySpain
http://www.unityspain.com/