Tutorial Unity: Crear Juego 3D Plataforma
Tutorial Unity: Crear Juego 3D Plataforma
de introduccion a Unity
Integración de un proyecto de
videojuego
Traduccion 3D Platformer Tutorial Building a 3D
Platform Game in Unity Tomado de www.unity3d.com
Realizada por www.c2estudio.com
Introducción
Unity es una poderosa herramienta para desarrollo
de juegos. Sirve para diferentes generos de juegos,
desde First Person Shooters (Juegos de primera
persona) hasta juegos de rompecabezas.
Con sus múltiples características, incluyendo mapas de alturas de terrenos, apoyo a la creación
de redes nativas, integración de física completa y secuencias de comandos, Unity puede ser
intimidante para los recién llegados, pero el dominio de sus herramientas es bastante sencillo y
gratificante.
Este tutorial le guiará por el proceso de construcción de un nivel completo un juego de
plataformas en 3D con vista en perspectiva de tercera persona. Esto incluye todo como los
controles del jugador, la detección de colisiones, algunas secuencias de comandos avanzados,
proyección de sombra, IA (Inteligencia Artificial) basica, añadir un HUD, cortos de escenas y
como añadir el audio.
Lo que aprenderá
Este tutorial se centra en el aspecto técnico de la construcción de un juego en Unity, que abarca lo
siguiente:
•Controladores de personajes
• Proyectores
• Fuentes de audio y clips de audio
• Múltiples cámaras (y cómo cambiar entre ellas)
• Sistema UnityGUI de scripting
• Controles de colisión
• Mensajes y eventos
• Iluminación
• Sistemas de partículas
• Sombras usando un proyector
• Scripting (IA, máquinas de estado, controles de reproducción)
Este tutorial se muestra cómo estas características se pueden utilizar juntas para crear un juego.
Lo que usted debe saber ya
En este tutorial hace un amplio uso de scripting por lo que debe estar familiarizado con al menos
uno de los lenguajes de scripting soportados: JavaScript, C # o Boo. (JavaScript se utiliza para las
secuencias de comandos en este tutorial.)
También se supone que está familiarizado con la interfaz de Unity y sabe cómo realizar las
operaciones básicas, tales como la localización de un objeto en una escena, añadir componentes a
un GameObject, y edición de propiedades en el Inspector.
Organización del Proyecto
Unity no intenta forzar una determinada manera de organizar los assets de su proyecto.
2
Usted puede preferir la organización de sus assets por tipo de assets, con carpetas separadas, por
ejemplo, "Texturas", "Modelos", "Los efectos de sonido" y así sucesivamente.
GameObjects y Componentes Abstractos
Unity, por diseño, coloca los assets de cada escena en el centro del proceso de desarrollo. Esto
hace un enfoque muy visual para el desarrollo del juego, con la mayoría de los trabajos que
impliquen arrastrar y soltar. Esto es ideal para la mayor parte del trabajo a nivel de diseño, pero
no todos los assets pueden ser mostrados de esta manera. Algunos assets son abstractos en lugar
de ser objetos visuales, así que están representados por iconos abstractos y gizmos ‐‐ Ej. audio y
luces ‐‐ o no son mostrados en la ventana Scene. Los Scripts estan en esta última categoría.
Los Scripts definen cómo los assets y GameObjects en una escena de Unity interactúan unos con
otros y esta interacción es la base de todos los juegos. Por esta razón, es generalmente un buen
plan mantener comentarios dentro de los scripts.
Este tutorial asume que usted puede leer los scripts proporcionados y comprender los
comentarios dentro de ellos. Sin embargo, cuando un script en particular, técnica o concepto es
importante, vamos a cubrirlo en detalle.
Archivos
La carpeta "Scene" contiene el resultado final: un menú principal de escenas, una escena de Game
Over y una escena que contiene el nivel de juego completo.
Este tutorial asume que usted ya sabe los controles básicos de Unity, tales como objetos de
posicionamiento, en una escena, así que la primera escena con la que comenzamos ya tiene el
escenario de base y algunos objetos en su lugar.
Convenciones tipográficas
Este es un largo tutorial que contiene una gran cantidad de información. Para hacerlo más fácil de
seguir, algunas convenciones simples son usadas:
Texto en cuadros como éstos contiene información adicional que puede ayudar a aclarar el texto
principal.
ntes y Tangentes
Codigo de Scripting aparecerá como se muestra a continuación:
Acciones que necesita llevar a cabo dentro de Unity se muestran así:
Haga clic aqui;
Entonces esto;
Luego haga clic en Reproducir.
3
Los nombres de scripts, los assets, los elementos de menú o el inspector de propiedades se
muestran en texto en negrita.
Convenios de Unity
Unity es un sistema de desarrollo único. La mayoría de los desarrolladores estan acostumbrados
a trabajar en un editor de código, usando el 90% de su tiempo editando código, e incluso escribir
código para cargar y utilizar los assets. Unity es diferente: es enfocado en los assets en vez de
enfocado en el codigo, el foco en los assets es similar al de una aplicación de modelado 3D. Por
esta la razón, vale la pena entender las principales convenciones y la terminología única para el
Desarrollo de Unity:
Proyectos
Un juego construido en Unity se compondrá de un proyecto. Contiene todos los elementos de su
proyecto, tales como los modelos, guiones, planos, menús, etc Normalmente, un archivo único
proyecto contendrá todos los los elementos de su juego. Cuando se inicia Unity, lo primero que
hace es abrir un Archivo de proyecto.
Escenas
Cada proyecto contiene uno o más documentos llamados Escenas. Una sola escena contendrá
un nivel de juego, pero elementos principales como una interfaz de usuarioo los menús de juego,
secuencia de GameOver o escenas importantes También pueden vivir en sus propios archivos de
escena. Juegos complejos incluso puede usar escenas enteras sólo para fines de inicialización. Así,
todos los niveles en un juego muy probablemente serán escenas, pero no todas las escenas
necesariamente será un nivel de juego.
GameObjects, componentes, Assets y Prefabricados
La clave para entender Unity es la relación entre un GameObject y un componente.
GameObjects
Un GameObject es el bloque de construcción fundamental en Unity. Un GameObject es un
contenedor de diferentes piezas de la funcionalidad de llamadas componentes. Un GameObject
casi siempre contiene más de un componente. Todo GameObjects contienen un componente
transform, que define su posición y orientación.
Jerarquías GameObject
El poder real de los GameObject es su capacidad para contener otros GameObjects, muy similar a
una carpeta en OS X Finder. Esto permite la organización jerárquica de GameObjects,
por lo que un complejo modelo o una plataforma completa de iluminación se puede definir en un
solo GameObject padre. (De hecho, la mayoría de los modelos aparecerán en Unity como una
jerarquía de GameObjects porque esto refleja la forma en que se definen en el paquete de
modelado.) Un GameObject definido dentro de otro GameObject se considera un GameObject hijo.
Componentes
Los componentes son los bloques de construcción de GameObjects. Sin ellos, el GameObject
no hará nada interesante.
Un componente puede representar a las entidades visibles, como las mallas, los materiales, los
datos de terreno o un sistema de partículas. Otros tipos de componentes son más abstractos,
tales como cámaras y Luces, que no tienen un modelo físico que los representa, en cambio, usted
verá una icono y unas directrices de alambre que ilustran sus valores fundamentales.
Un componente esta siempre unido a un GameObject, no puede vivir solo. Multiples componentes
pueden conectarse a un mismo GameObject. GameObjects puede soportar múltiples
Componentes de ciertos tipos ‐‐ un GameObject puede contener cualquier número de scripts, por
ejemplo. Pero otros, como los utilizados para definir sistemas de partículas, son exclusivos y
sólo puede aparecer una vez en cualquier GameObject único. Por ejemplo, si desea definir
múltiples sistemas de partículas, normalmente se utiliza una jerarquía de GameObjects, cada uno
que contiene su propio conjunto de componentes de sistema de partículas.
4
Assets
Todos sus assets importados aparecen en el panel de proyectos y pueden ser casi cualquier cosa:
un material simple o la textura, archivos de audio, o incluso un GameObject prefabricado
(conocido como "prefab").
Por ejemplo, un personaje de jugador de Prefab se podría definir como un solo Asset, que
contiene el modelo y sus animaciones asociadas. También podría contener scripts de
componentes, clips de audio y cualquier otro componente que necesita para funcionar, por lo que
podría simplemente arrástrarlo en una escena e inmediatamente tener un avatar en pleno
funcionamiento.
Los iconos personalizados & Gizmos
Puede decirle a Unity que muestre los iconos personalizados y otra información visual para sus
assets si lo desea. Vamos a ver un ejemplo de esto en el siguiente capítulo.
Los assets de su proyecto se muestran en el panel Proyecto (Project). Al colocar un asset en la
Escena, aparece en el panel jerarquía (Hierarchy), que define el contenido de la escena. (Una
escena es el equivalente del escenario en un teatro. Puede ser un nivel, un menú, un salón de
juego multijugador) el panel Project se mantiene en todas las escenas en su proyecto.
Prefabricados
Un prefab es un asset que ha sido definido como una plantilla. Es para Unity lo que una plantilla
de documento es para una aplicación de procesamiento de textos. Cuando se coloca un prefab en
la escena, Unity coloca un enlace al Prefab en el panel de jerarquía, no una copia completa. Esto
se llama instanciación. Cada enlace que se haga se conoce como una instancia del Prefab.
Si hace clic en un prefab en el panel de proyectos y ajusta su configuración, usted encontrará que
esos cambios se reflejan automáticamente en todas las instancias en la escena. Esto hace que
los prefabs sean ideales para muchos elementos reutilizables, tales como las balas, enemigos, etc.
Si usted encuentra un enemigo que no se está comportando correctamente, sólo tendrá que
ajustar el script o configuración del Prefab original en lugar de editar cada uno de ellos en la
escena de forma individual.
Sin embargo, si hay que ajustar un par de campos en un caso concreto de un prefab.
Usted puede hacer esto también: estos cambios sólo afectan a esa instancia particular.
Prefabricados son mostrados en texto azul, tanto en el proyecto como en el panel de jerarquía.
NOTA Un ejemplo de Prefab no puede tener componentes adicionales ya que de hacerlo, se
romperá el vínculo con el Prefab original. Unity le avisará si intenta hacer esto. Unity, sin embargo,
le permite actualizar el Prefab original con dichos cambios después de que el enlace fue roto.
Agradecimientos
Este tutorial es una version en español del Tutorial realizado por Unity 3D y no podría haber sido
producido sin las siguientes personas:
David Helgason, Joachim Ante, Tom Higgins, Sam Kalman, Keli Hlodversson, Nicholas
Francis, Aras Pranckevičius, Bosque Johnson y, por supuesto, Ethan Vosburgh que produjo
los assets para este tutorial.
Traducido por C2 Estudio S.A.
5
Primeros pasos
Cada juego de plataforma tiene un personaje
que el jugador controla.
Nuestra estrella es Lerpz.
Animación de Lerpz
En este capítulo vamos a ver:
• Implementación del jugador de tercera persona y controles de camara
• Control y mezcla de animaciones
• Uso de sistemas de partículas para aplicar a los propulsores del jetpack
• Agregar una blobshadow para el jugador
• Mantener el estado del jugador
• Manejo de salud de los jugadores, la muerte y el renacimiento.
Antes de comenzar, tenemos que saber lo que este juego se trata. En resumen,
Necesitamos ...
La historia
Nuestro héroe es Lerpz: un extranjero visitando Robot World Version 2. Este sustituye Robot
World Versión 1, que sufrió un fallo de segmentación y de repente se estrelló en su sol hace
muchos años.
Lamentablemente, Lerpz ha tenido mala suerte: su nave espacial ha sido incautada por la
corrupta policía local. Después por todos lados, Lerpz ha encontrado su nave espacial, pero
¿Cómo puede recuperarla?
Lerpz sabe que si recoge todas las latas de combustible, la energía utilizada sobrecargará el
sistema de seguridad. Esto apagará la reja del depósito municipal y la nave espacial de Lerpz
quedara libre. Lerpz puede entrar en su nave espacial, agregar el combustible
y volar hacia la libertad.
Los guardias robot intentarán detener a Lerpz, pero por suerte, no son particularmente
brillantes.
Presentación de Lerpz
Abra el proyecto y vea Scenes>TheGame
Nuestro primer paso es añadir Lerpz a nuestra escena:
Mantenga el objeto Jugador seleccionado, mueva el ratón sobre la vista de escena y presione
la tecla F (foco) para que la vista se centre en el modelo de Lerpz.
6
Mueva a Lerpz hacia la plataforma elevada con el salto (el nicho con los triangulos
amarillos), cerca de la cárcel. (Ver la captura de pantalla siguiente.)
Si usted hace clic en Reproducir (Play), debería ver a Lerpz de pie en el patio fuera de la cárcel.
En esta etapa, Lerpz no se puede mover y la cámara también debe estar vinculada a personaje.
Haga clic en el botón Reproducir de nuevo para detener el juego.
Tenemos que hacer que Lerpz se mueva. Pero en primer lugar, tenemos que retroceder un
momento y dar una vistazo a nuestra cámara.
Posicionamiento de Lerpz en la escena.
Cámaras de Tercera Persona .
En un juego de primera persona, la cámara es el punto de vista del jugador, por lo que no hay
necesidad de que preocuparse de hacer que siga otro objeto alrededor de la escena. El jugador
controla la cámara directamente. Las camaras de primera persona por lo tanto son relativamente
fácil de implementar.
Sin embargo, un punto de vista de la cámara de tercera persona requiere una cámara que pueda
seguir el jugador por todas partes. Esto parece bastante sencillo hasta que te das cuenta de la
cámara también tiene que saber cómo evitar objetos que se encuentren entre el personaje del
jugador y el punto de vista de la cámara.
Esto puede conseguirse utilizando raycasting para comprobar si hay objetos no deseados entre la
cámara y el avatar del jugador, pero hay algunos casos especiales a considerar. Por ejemplo:
• ¿Qué pasa si un enemigo se interpone entre la cámara y nuestro avatar del jugador?
• ¿Cómo deben funcionar los controles del jugador ? ¿Deberían ser relativos al punto de vista de la
camara? Si es así, esto podría ser muy confuso si la cámara se mueve inesperadamente para evitar
un obstáculo.
Una serie de soluciones para las cámaras en tercera persna se han probado en los últimos años.
Puede afirmarse que ninguno ha sido 100% perfecto. Algunas soluciones desvanecen todo lo que
esta entre ellos y su enfoque, haciendo paredes o enemigos semitransparentes.
Otras opciones incluyen cámaras que siguen el jugador alrededor, pero que, en caso necesario,
Pueden moverse a través de paredes y edificios para mantener la vista del jugador consistente.
7
El proyecto que viene con este tutorial incluye algunas secuencias de comandos de cámara
diferente, pero para los efectos de este tutorial, vamos a utilizar SpringFollowCamera. Usted lo
encontrará en el Panel de Proyecto dentro de la subcarpeta de Cámara de la carpeta Scripts.
Haga clic en Reproducir.
Usted recibirá un mensaje de error. Esto aparece en la parte inferior de la ventana de Unity.
Mensaje de error “No Target”.
SUGERENCIA Siempre que sea posible, la ventana de registro de depuración mostrará una línea que
une al GameObject del problema en la jerarquía, (o el panel de proyectos si el fallo está en un
Prefabricado o script). Usted puede ver esta línea en la pantalla de arriba.
El tipo de error es uno UnassignedReferenceException es probable que lo veas muy
frecuentemente si eres nuevo en Unity. Suena espantoso, pero lo único que significa es que una
variable de un script no se ha establecido. El registro de depuración explica esto también, así que
vamos a hacer lo que le sugiere:
La propiedad de destino esta definida como None (Transform). Esto define adonde queremos
que apunte la camara, así que vamos a establecer el siguiente:
Parar el juego si no lo ha hecho ya.
8
Si no está seleccionada, haga clic en el objeto NearCamera en el panel de la Jerarquía.
Arrastre el GameObject Player desde el panel de jerarquía al Campo Target.
Cambios en caliente
Cuando usted está jugando el juego, Unity le permitirá ajustar las propiedades de los distintos
objetos del juego y de los componentes en el juego. Sin embargo, no se salvarán! En el momento de
detener el juego, los cambios serán descartados!
Si desea que los cambios se mantengan, siempre se detiene primero el juego!
Si usted hace clic en Reproducir ahora, la cámara no funcionará. Usted verá un error relativo al
Script SpringFollowCamera. El objetivo necesita tener un script ThirdPersonController unido
a él. Esto es porque una cámara de tercera persona está estrechamente vinculada a los controles
del jugador: necesita saber lo que el jugador está haciendo para que pueda reaccionar en
consecuencia.
La configuración final debería ser como se muestra en la siguiente imagen:
Propiedades del script SpringFollowCamera.
Experimente con los números si no le gusta la forma en que funciona la cámara, esto es algo
subjetivo a juicio personal y no hay ninguna configuración correcta para algo como esto.
Esta es la primera de una serie de dependencias con las que tenemos que lidiar.
Completar la conexión entre la cámara y el reproductor arrastrando el script
ThirdPersonController desde el folder Scripts>Player en el panel de proyectos
a nuestro GameObject Player (en el panel de jerarquía). (Esto romperá la conexcion de Prefab)
El script ThirdPersonController también tiene sus propios requisitos y dependencias.
El más importante de ellos es el componente Character Controller. Afortunadamente, el script
le informa acerca de esto a Unity y este componente es agregado de forma automatica.
9
Conexiones y dependencias.
Unity Sobresale en la exhibición de assets visuales, pero estos también tienen que estar
conectados entre sí para asegurar la interactividad que esperamos de un juego. Estas conexiones
son difíciles de
mostrar visualmente.
Estas conexiones son conocidas como las dependencias, y es lo que se obtiene cuando un objeto
requiere de un segundo objeto para funcionar. El segundo objeto, a su vez, puede requerir aún
más
objetos de trabajo. El resultado es que sus assets están vinculados unos a otros con
innumerables trozos de cadena virtual – scripts – uniendolos todos juntos para hacer un juego.
Definir correctamente todas estas dependencias es un elemento clave del diseño del juego.
Ahora tenemos que agregar una etiqueta a nuestra GameObject Jugador. Esto es para que los
scripts puedan encontrar el Jugador en la escena, simplemente diciendole a Unity que encuentre
el GameObject con dicha etiqueta.
Selección de la etiqueta Player.
NOTA Las Etiquetas que figuran en el menú mostrado arriba son proporcionadas por Unity de
forma predeterminada.
Vamos a aprender a crear nuestras propias etiquetas y capas más tarde.
La etiqueta se utilizará más adelante, así que volvamos al controlador de personajes y nuestro
script.
10
Scripts de CharacterController y ThirdPersonController en su lugar.
Nuestro próximo paso es ajustar el Character Controller. Por el momento, el Control de colisión
(Collider) en forma de cápsula que utiliza se encuentra demasiado lejos en el eje Y, por lo que
Lerpz está en el aire. (Usted puede ver la posición del Collider en la vista de escena: es el largo
alambre cilíndrico verde) Tenemos que cambiar el valor del Centro de Y.
Ajuste de la cápsula que controla la colisión del personaje se muestra como un alambre verde.
Posicione el Collider de la cápsula como se muestra en la pantalla de arriba. (Un poco de
experimentación sugiere poner el Centro del Contralor del personaje en Y a 1.03 Esto, alineará
su extremo inferior con los pies perfectamente.)
11
Si usted hace clic en Reproducir ahora, Lerpz ahora debe moverse cuando utiliza las teclas de
control con los pies firmemente en el suelo.
El controlador de personajes y el script de Controlador de Tercera
Persona
En la mayoría de los juegos, el avatar del jugador es capaz de hazañas físicas imposibles, como
girar y detenerse instantáneamente, saltar distancias inverosímiles y otras acciones que sería
muy difícil de modelar con la física tradicional. El Character Controller por lo tanto separa
nuestro avatar del jugador desde el motor de física, proporcionando controles de movimiento
básico.
El Contralor de personajes simplifica el movimiento de un jugador (y muchos tipos de personajes
diferentes). Se trata de un Collider de cápsula atado a un sistema de movimiento de base, que
permite que nuestro personaje pueda moverse, subir escaleras y cuestas hacia arriba o hacia
abajo. Tú puedes cambiar el tamaño máximo de las pendientes en el Inspector.
El Character Controller se utiliza normalmente con un script. Esto habla con el controlador de
personaje y amplía sus capacidades para satisfacer las necesidades del juego.
En nuestro proyecto, el script de Third Person Controller realiza esta función y agrega el apoyo
necesario para nuestro juego de plataformas. Lee el joystick, teclado, ratón u otro dispositivo de
entrada y actúa en consecuencia como el control del avatar del jugador.
El administrador de entradas de Unity (Edit>Project Settings>Input Manager) le permite definir
cómo los dispositivos de entrada controlan el jugador.
Nota: No hay nada especial acerca de los scripts que estamos usando para el jugador. Son scripts
normales de Unity que se han construido para este proyecto. No hay un scriot para controlar
personajes por defecto.
El script de Controlador de Tercera Persona es ya parte de los prefabricados, asi que no hay
necesidad de añadirlo.
El siguiente paso es hacer Lerpz se anime correctamente y añadir los movimientos adicionales,
tales como saltar y golpear ...
Animando a Lerpz
En este punto, Lerpz solo se desliza a través del paisaje. Esto es porque el Character Controller no
maneja animación. No sabe nada acerca de nuestro modelo de jugador o secuencias de animación
que se aplican a cada movimiento. Necesitamos conectar a Lerpz con sus secuencias de
animación y esto se hace con el script ThirdPersonPlayerAnimation.
Utilice el menú de componentes para agregar el script ThirdPersonPlayerAnimation al
GameObject Player.
Si usted hace clic en Reproducir ahora, verá a Lerpz con su animación correcta.
Entonces, ¿qué está pasando aquí? ¿Qué hace este script? La respuesta está en cómo gestiona
Unity datos de animación de personajes.
Character Animation
Las secuencias de animación de los personajes se crean dentro de un paquete de modelado, como
3D Studio Max, Maya, Blender o Cheetah3D. En la importación en Unity, estas secuencias se
extraen automáticamente y se almacenan en un componente de animación.
Estas secuencias de animación se definen en un esqueleto virtual, que se utiliza para animar
el modelo básico. Estos esqueletos definen cómo la malla del modelo ‐‐los datos importantes en
12
la definición de las superficies visibles del modelo en sí mismo ‐‐ es modificada y transformada
por el motor para producir la animación necesaria.
armaduras
Mezcla de animación
Las Animaciones de los personajes suelen ser mezcladas para proporcionar la flexibilidad
necesaria para un juego. Por ejemplo, un ciclo de recorrido animado podría mezclarse con una
serie de animaciones discurso, el resultado es un personaje que camina y habla al mismo tiempo.
La mezcla se utiliza también para producir unas suaves transiciones entre las animaciones, como
la transición entre un ciclo de andar y una secuencia de golpe.
Tenemos que usar un script para decirle a Unity que necesitamos cambiar las animaciones,
cuando se necesita la mezcla de la animación y cómo debe hacerse. Aquí es donde entra de Nuevo
el scripting.
El Script de Animación de Jugador de Tercera Persona
El modelo Lerpz que estamos usando usara las siguientes animaciones en el tutorial:
• Walk (Caminar) -- Ciclo de andar normal.
• Jump Fall (saltar un muro) -- Animación backflip reproduce cuando Lerpz salta de una pared.
13
caminar, correr, saltar, etc son bastante similares sin importar que personaje sea. Sin embargo, los
movimientos de ataque y defensa tienden a ser mucho más variados. En algunos juegos de
plataforma, el personaje del jugador podría tener un arma, y en otro, podría realizar un
movimiento de artes marciales.
En este tutorial, Lerpz tiende a golpear a su rival muy duro con el puño. La animación es una
animación de puño simple.
Gizmos
ThirdPersonCharacterAttack también incluye una característica de prueba útil: un Gizmo que
dibuja una esfera para representar a la zona afectada por la acción de puño de Lerpz. Los Gizmos
son elaborados dentro de uno de las das funciones de Gizmodrawing de manejo de mensajes. En
este ejemplo, la malla Gizmo es una esfera amarilla que establece en la posición de golpe y
muestra su área de efecto. Es elaborado en respuesta a la función OnDrawGizmosSelected().
Esta función debe ser estática y será llamado por el Editor de Unity. Una alternativa es
OnDrawGizmos(), que es llamada por el Editor de Unity cada ciclo Update, independientemente
de si el padre GameObject ha sido seleccionado.
El JetPack
Jetpack de Lerpz en acción.
En este punto, nuestro personaje puede correr y saltar alrededor, pero su jetpack aún no está
funcionando. Lerpz utiliza el jetpack para disminuir su tasa de descenso. El movimiento ya está en
su lugar, pero el fuego del jetpack no se anima. Para que funcionen los chorros, vamos a necesitar
añadir dos sistemas de partículas y un componente de punto de luz. Los sistemas de partículas
producirán un efecto de llamas, mientras la luz de punto dará la ilusión que las llamas actúan
como fuente de iluminación.
TIP Lo ideal sería tener un punto de la fuente de luz para cada jet, pero los chorros de escape
están lo suficientemente cerca entre sí para usar sólo uno. Ya que las luces son de alto costo
computacional, esto es una de las muchas optimizaciones que se deben realizar en el desarrollo de
videojuegos.
¿Qué es un sistema de partículas?
Los Sistemas de partículas emiten docenas de partículas normalmente planos en 2D o sprites al
mundo 3D. Cada partícula se emite a una velocidad establecida y la velocidad, viven un cierto
tiempo. Dependiendo de la configuración y los materiales utilizados, estos sistemas de partículas
puede ser utilizados para simular algo de fuego, humo, agua y hasta explosiones estelares.
14
Adición de los Sistemas de Partículas
Utilice el menú de GameObject para crear un GameObject vacío en el panel de jerarquía.
Cambie el nombre del GameObject por "Jet".
Con el nuevo GameObject seleccionado, añadir:
Un emisor de partículas del elipsoide (Ellipsoid Particle Emitter)
Un animador de partículas (Particle Animator)
Un Collider de partículas de Mundo (World Particle Collider)
Un Particle Renderer
Desactive la casilla "Enabled" en la ventana para el componente de Particle Renderer . Esto
lo desactiva temporalmente.
Posicione el Jet directamente debajo del chorro de escape derecho de Lerpz
Reactive el Particle Renderer .
Ajuste la configuración del emisor de partículas del elipsoide, como se muestra a
continuación:
Configuración del emisor de partículas elipsoide.
15
Estos ajustes resultan en un pequeño chorro de partículas que vamos a utilizar para simular el
chorro de la llama.
SUGERENCIA Si las partículas no se mueven directamente hacia abajo, utilice las herramientas de
rotación de Unity para rotar nuestro objeto hasta que el chorro se mueve en línea con el jetpack.
Cuando hayamos terminado, el sistema de partículas se adjuntará al objeto hijo en la jerarquia del
Player “torso”. Esto hará que el chorro siga los movimientos del jugador. En este punto, sin
embargo, estamos interesados principalmente en conseguir que se vea bien, así que no te preocupes
demasiado por una colocación precisa.
El tamaño mínimo y Tamaño máximo defininen el rango de tamaño de las partículas. Min y
Max de Energía definen la vida útil mínima y máxima de las partículas.
Nuestro partículas vivirá sólo por un tiempo corto 0,2 segundos en este caso, antes de
apagarse.
Hemos establecido la cantidad de partículas que emiten a 50. El rango Min y Max de emisión
define cuántas partículas que queremos en la pantalla en cualquier momento. El resultado
debería ser un buen flujo de partículas.
NOTA hemos inhabilitado "Simular en Worldspace" aquí. Esto ayuda a dar la impresión de que
tenemos un chorro de gas caliente y rápido más que una llama mucho más lenta.
Ahora bien, establecer la configuración de los componentes Particle Animator como se muestra:
Configuración de animador de partículas. Los valores en la tabla de definir las entradas de Animación de color. No se olvide de
configurar los otros ajustes también!
Color Rojo Verde Azul Opacidad
El Particle Animator animará los colores de las partículas a medida que envejecen. Las
partículas comienzan en blanco, pasando por el amarillo oscuro y anaranjado mientras nuestro
jet virtual se enfría. Desde que vamos a renderizar una textura en cada partícula, el animador de
partículas se utiliza para teñir esta partícula, por lo que la animación de color será sutil, pero
efectiva.
El selector de color de diálogo que aparece cuando haces clic en un color también ofrece una
"opacidad" con control deslizante. La tabla con los valores de color que también lo incluyen.
Mediante la reducción de la opacidad de todo el ciclo de animación, la partícula 'llamas' van a a
desaparecer como cuando se enfrían.
El siguiente es el Particle Renderer . Este componente dibuja cada partícula, por lo que debe
explicarsele cómo van a aparecer las partículas. También define el material que se utilizará para
representar cada una de las partículas. Queremos un efecto de chorro de llamas , por lo que
deberá utilizar el material "fire add", que se puede encontrar en: Particles>Sources>Materials>
16
Fire add
TIP Este asset también se incluye en la carpeta Standard Assets.
Establecer los valores de este componente de la siguiente manera:
Configuración de Particle Renderer.
La variable de estiramiento de particulas (Stretch Particles) le dice Unity si las partículas deben
ser estiradas si se están moviendo a gran velocidad. Queremos que las partículas se estiren un
poco de acuerdo con su velocidad. Esto añade una señal visual sutil y hace que las formas que
estamos usando para esta mezcla reaccionen mejor entre sí.
NOTA Las configuraciones de Cast Shadows y Recieve Shadows no tienen ningún efecto a menos
que utilice un shader personalizado. Este es un tema avanzado más allá del alcance de este tutorial.
Adición de la Luz
Nuestro jet se ve bien, pero en realidad es una ilusión: EL Sistema de partículas sólo escupe un
montón de pequeñas imágenes, pero el resultado no emite luz. Para completar la ilusión,
vamos a crear un GameObject Pointlight por separado. Vamos a encenderlo y apagarlo al
mismo tiempo que los chorros. El resultado será un chorro de fuego que ilumina su entorno
inmediato. (Sólo se utiliza una sola luz, en lugar de una luz por chorro, esto ahorra potencia de
procesamiento mientras que mantiene la ilusión.)
Cree un nuevo GameObject de Pointlight.
Nombre este "Jet Light" y posicionelo entre los dos chorros del jet de Lerpz. (Volveremos a
nuestro sistema de partículas Jet en breve.) Esta luz va a crear la ilusión de que los chorros son
emisores de luz.
Para este efecto funcione, necesitamos un punto de luz brillante con una alta intensidad.
17
Seleccione la luz y ajuste la configuración como se muestra:
Configuración de la Luz del Jet.
¿Por qué no las sombras?
Las sombras son computacionalmente costosas para la mayoría del hardware. Tiene sentido evitar
cálcularlas, si podemos. Los jets no son muy grandes, por lo que sólo tendrá que iluminar de la
espalda de Lerpz's. La luz de punto también se verá reflejada en el escenario cercano, pero no será
lo suficientemente brillante para que la la falta de sombras sea notable.
El siguiente paso es actualizar el GameObject Player para incluir nuestro jet y los objetos de luz.
Para ello, primero añadimos nuestro Jet al panel de proyectos como Prefab:
En el panel Proyectos, seleccione la carpeta Player (vacía), a continuación, haga clic en
Crear...
En el menu de lista desplegable, seleccione Prefab. Esto creará un objeto de Prefab vacío
Adentro.
Cambie el nombre de Prefab vacío a Jet.
Arrastre nuestro objeto Jet desde el panel de jerarquía en nuestro Prefab nuevo.
El nombre de Jet en el panel de jerarquía debía ponerse azul para mostrar que está ahora
vinculado un prefab. Vamos a utilizar dos instancias de nuestro Jet prefabricado para el jet pack
de Lerpz.
Color Rojo Verde Azul Opacidad
Eliminar nuestro objeto Jet original desde el panel de la Jerarquía. (Sin embargo, dejar la luz
del Jet donde está!)
Ahora agregamos el jet (dos veces) y la luz (una vez) a nuestro jugador:
Abrirla hasta que encuentre el objeto secundario torso.
18
Ahora debería tener una jerarquía de objetos que se ve algo como esto:
Jerarquía del Jetpack
Utilice herramientas de manipulación de Unity para posicionar cada Prefab Jet sobre su
respectivo chorro de salida en el modelo de Lerpz. Puede que tenga que girar el chorro, de modo
que las partículas vayan en la dirección correcta.
Mueva el la Luz Jet a un punto entre los dos Jet Prefabricados.
Cuando hayas logrado esto, Lerpz Ahora debe tener dos jets en llamas que brotan de su jetpack
cuando se mueve. Estamos casi listos!
El paso final es hacer que los Prefabricados Jet y objetos Jet de luz se activen sólo cuando este
salte. Esto se logra a través de scripts.
19
El Jetpack de Lerpz en acción.
Blob Shadows
Lerpz debe ser fácil de identificar en todo momento, de modo que los jugadores no pierdan la
pista de sus avatares cuando el juego se hace visualmente complejo. La mayor parte de este
trabajo corresponde a los artistas y los el diseñadores del juego, pero hay algunos elementos que
tienen que ser manejados por Unity.
Uno de los más importantes es el sombreado y la iluminación. Para ayudar el rendimiento,
los efectos de iluminación son a menudo prerenderizados en las texturas del artista con una
técnica conocida como "Baking". Esta técnica sólo funciona bien sobre los objetos estáticos, tales
como escenarios y accesorios fijos. (Hemos evitado deliberadamente esta técnica en los assets de
este tutorial.) Un personaje que camina bajo una farola necesita reaccionar a la luz en tiempo
real. El suelo bajo el personaje puede tener la iluminación con Baking, pero el personaje no puede
utilizar este truco, y también necesita reaccionar a la luz.
La solución es colocar las luces dinámicas, donde es necesario. Si utiliza texturas con Baking,
recuerde añadir una luz donde quiera que se implica esta por la iluminación, pero haga que las
luces sólo afecten a los objetos en movimiento. Las luces ya se han colocado en esta escena para
usted.
Esto deja un último elemento: las sombras.
En un juego de plataformas en 3D, la sombra juega un papel clave ya que nos dice donde el
personaje caerá si esta saltando o cayendo. Esto significa que debe tener una sobra visible lo cual
no es el caso en este momento.
Las sombras pueden ser producidos a partir de luces, con la sombra siendo computarizada y
generada en tiempo real por el motor gráfico. Sin embargo, las sombras son costosas en términos
de potencia de procesamiento. Además, no todas las tarjetas gráficas puede calcular sombras
rápidamente o con eficacia; las antiguas tarjetas pueden no ser capaces de hacerlo en absoluto.
Por esta razón, vamos a utilizar una sombra Blob para Lerpz.
Añadir una sombra Blob
Una sombra Blob es una truco. En lugar de emitir rayos de luz y comprobar si afectan cualquier
cosa, simplemente se proyecta una imagen oscura ‐ en este caso, sólo una mancha circular negra ‐
debajo de nuestro personaje. Esto es más rápido y más fácil para la tarjeta gráfica, así que debería
funcionar bien en todas las gamas de hardware.
Unity incluye un BlobShadow prefabricado en su colección de Assets estándar, por lo que se
podra utilizar esto en lugar de crear uno propio. Este asset ya se ha importado y se añade a
el proyecto en la carpeta BlobShadow. Abra esta carpeta y haga clic en el prefab blob shadow
projector y arrástrelo a nuestro nivel superior del objeto Player en el panel de jerarquía. Esto debe
agregar el proyector justo por debajo del nivel superior en la jerarquía de nuestro objeto Player:
20
El Prefab blob shadow projector en la jerarquía del Jugador.
A continuación, tendrá que modificar la posición del proyector de sombra de blob y datos de
rotación de modo que este directamente encima de nuestro personaje y apuntando directamente
hacia el suelo.
Ahora use las vistas lateral y superior para mover el proyector directamente sobre la cabeza
de Lerpz. Es posible que desee mover hacia arriba o hacia abajo un poco hasta que esté satisfecho
con el tamaño de sombra.
Crear una nueva capa
En este punto, usted habrá notado que la burbuja también está siendo proyectada en Lerpz.
No queremos que esto suceda. Hay dos opciones para evitar esto: mover el valor del Near Clip
Plane más lejos del proyector, o simplemente decirle que no proyecte en los objetos en capas
específicas. Vamos a utilizar la segunda opción.
¿Por qué no ajustar Near Clip Plane?
Esta técnica puede parecer más fácil a primera vista, pero el plano tendría que ser ajustado
por scripting para tener en cuenta las animaciones de Lerpz. Sus pies se mueven más lejos
cuando salta y se acercan un poco más cuando las aterriza de nuevo. Ya que la sombra siempre
debe ser proyectada sobre el suelo, esto significa que el Near Clip Plane no puede seguir siendo el
mismo en toda estas secuencias.
Abra el GameObject Player.
Abra el menú desplegable de Layer en el Inspector.
21
Añadir un nuevo Layer usando el Administrador de etiquetas.
Haga clic en el menú desplegable "Layer" pongalo en el nombre de la capa nueva,
noShadow. Unity le preguntará si desea aplicar esto a todos los GameObjects hijo: haga clic en
"Cambiar las Capas hijas".
Lo siguiente que necesitamos decirle al proyector Shadow Blob que no proyecte en los objetos
en este Capa.
Muestre las propiedades de la sombra de blob en la ventana y mire la entrada Ignorar
Capas en el componente del proyector.
Propiedades del blob shadow projector.
Si ahora juega el juego y se mueve a su alrededor debe ver la sombra comportarse más o menos
como se esperaba .... excepto si saltas cerca de las objetos de combustible para recolectar. Si
intentas hacer esto, podrás ver el item mostrando la sombra también.
22
Queremos que los artículos recolectables se destaquen en todo momento, tiene sentido que el
proyector de sombras blob evite estos también.
Vamos a mirar estos artículos recolectables con mucho más detalle en el capítulo siguiente, pero
vamos a solucionar este problema ahora, mientras estamos aquí.
En primer lugar, detenga el juego.
Ahora vaya al panel de proyectos y busque los objetos FuelCellPrefab y
HealthLifePickUpPrefab. Usted los encontrará dentro de la carpeta Props.
Seleccione el objeto raíz de cada uno de Prefab y establezca su Layer a noShadow, como se
muestra a continuación:
Cambiar Layer a "noShadow"
NOTA Al hacer un cambio a un objeto primario, Unity a menudo se preguntan si el cambio
debería aplicarse también a los hijos de dicho objeto. Si lo hace, puede ser peligroso si usted no ha
pensado en todas las ramificaciones.
En este caso, queremos que todos los objetos secundarios de los GameObjects "FuelCellPrefab" y
"HealthLifePickUpPrefab" esten en la misma capa noShadow , así que cuando
Unity pide, propagar los cambios seleccióne que esta de acuerdo.
Conceptos de scripting
La mayoría de los scripts están centrados en un concepto popular en el desarrollo del juego: La
maquina de estado finito. Una máquina de estados finitos esencialmente define un sistema de
interacción de condiciones, conocidos como estados.
Un estado puede ser casi cualquier cosa, por ejemplo si un objeto se debe renderizar,
si debe ser sujeto a las leyes de la física, si enciende o no una sombra, si puede rebotar, su
posición en una pantalla, y así sucesivamente. El panel de Inspector nos permite cambiar
muchos Estados, directamente, porque estos estados son comunes a casi todos los juegos.
Sin embargo, hay otro tipo de Estado que es específico para el juego en sí. Unity no sabe que el
avatar del jugador es un extraterrestre, cuánto daño puede soportar Lerpz o que posee un
jetpack. ¿Cómo puede Unity saber de la conducta de los guardias robot o cómo deben interactuar
con Lerpz?
Aquí es donde los scripts son utiles. Usamos scripts para agregar la interacción y la
administración de estados específicos para nuestro juego.
Nuestro juego tendrá que estar al tanto de una serie de estados. Estos incluyen:
• La salud del jugador;
• El número de objetos de combustible que el jugador ha recogido;
• Si el jugador ha acumulado suficiente combustible para desbloquear el campo de fuerza;
• Si el jugador se ha parado sobre una plataforma de salto;
• Si el jugador ha tocado un item para recolectar;
• Si el jugador ha tocado la nave espacial;
• Si el jugador ha tocado un punto de reaparecer;
• Si el Game Over o pantallas de inicio debe ser mostrado;
• ... y mucho más.
23
Muchos de estos estados requieren que se realicen pruebas contra los estados de otros objetos
para garantizar que están al día. A veces, incluso se necesitan de los estados intermedios, para
ayudar a una transición. Por ejemplo, recoger una lata de combustible obliga a una verificación
para ver si el jugador tiene las suficientes para apagar el campo de fuerza.
Organización y Estructura
En este tutorial las máquinas de estado para el jugador, el nivel y los enemigos se manejan
por un puñado de scripts relacionados con diversos GameObjects. Estos scripts se comunican
entre sí, enviando mensajes y llamando funciones de cada uno.
Hay un número de maneras en que podemos establecer estos vínculos:
• Para añadir un enlace expuesto en la ventana del Inspector, en el que se coloca el objeto en
cuestión. Esto es ideal para scripts de proposito general que van a ser reutilizados en otros
proyectos.
Este es lo más eficiente ya que el script simplemente arranca los datos de la variable relevante
y no necesita hacer ninguna búsqueda. Sin embargo, se asume que usted sabe de antemano
exactamente qué objeto o componente que será enlazado.
Nosotros usamos esta opción para las cámaras en LevelStatus. (Esta secuencia de comandos, ya
está linkeada al GameObject Nivel.) Esto nos da la flexibilidad de la creación de múltiples
cámaras, una para de escena del nivel "desbloqueado" y otra para la secuencia de "nivel
completo". En la práctica, sólo estamos utilizando dos cámaras en el juego, uno para el jugador y
nivel completo y la otra para la escena "desbloqueado". Pero la opción está ahí para cambiar esta
situación.
• Estableciendo un vínculo dentro la funcion Awake () del script. La funion Awake () es llamada
en cada script que usted escriba antes que el primer evento Update se desencadene en el
GameObject al que esta pegado. Configurar el enlace aquí le permite almacenar en caché el
resultado para su uso posterior en una funcion Update(). Normalmente, se crearia una variable
privada con un enlace a otro GameObject o componente al que necesite tener acceso dentro de su
script. Si usted necesita hacer un GameObject.Find () para localizar el objeto, es mucho mejor
hacerlo una sola vez, dentro de Awake () debido a que GameObject.Find () es bastante lento.
Esta opción es más adecuada para aquellas situaciones en las que no necesita la flexibilidad de la
primera opción, pero no quiero tener que realizar una búsqueda complicada para el objeto en
cada ciclo de juego. La solución es, por tanto, buscar el objeto cuando el script ya fue despertado,
almacenando los resultados de la búsqueda para su uso en la sección de Update.
Por ejemplo, el script LevelStatus, que maneja el estado del nivel, guarda en caché enlaces a
varios otros objetos, incluido el objeto Player. Sabemos que estos no van a cambiar, así que
bien podríamos hacer que la maquina haga este trabajo por nosotros.
• Establecer un enlace durante la funcion Update (). Esta función se llama al menos una vez
por ciclo de juego, así que es mejor evitar el uso de llamado de funciones lentas aquí. Sin
embargo, las funcionesGameObject.Find () y getComponent () pueden ser bastante lentas.
Esta opción se utiliza para aquellas situaciones donde el objeto que usted necesita podría
cambiar en cualquier momento durante el juego.
Por ejemplo, ¿En cuál de los múltiples puntos de Reaparición en la escena de este tutorial debería
Reaparecer el jugador? Esto claramente cambia mientras el juego se está ejecutando, por lo que
necesitamos manejar este caso de la manera correcta.
El problema con esto es que es demasiado lento, así que es mejor diseñar para que no sea
necesario hacer esto a menudo.
24
Scripts en un entorno de desarrollo visual
Unity es una herramienta inusual ya que se centra en los assets visuales en lugar de los vínculos y
las conexiones entre ellos. Un proyecto de Unity grande puede tener docenas de scripts de distintas
complejidades interconectados alrededor de la Jerarquía, por lo que el diseño utilizado para este
tutorial usa algunas tecnicas de programacion orientada a objetos.
El script que trata con una parte específica de la máquina de estado por ejemplo, Animacion del
Jugador debería también el que realiza un seguimiento de las variables de estado correspondientes.
Esto puede hacer las cosas un poco complicadas cuando un script debe tener acceso a una variable
de estado almacenada en otro script, por lo que algunos scripts almacenan algunos valores en
caché para realizar el acceso a la información más rápido. Esta técnica también de vez en cuando
resulta en cadenas de comandos, donde una función en un script simplemente llama a una función
similar en otro script. El manejo de la muerte y de la salud del jugador es un ejemplo de ello.
Si lo desea, puede volver al GameObject Player en un prefab con todos nuestros cambios, de
manera que usted pueda reutilizarlo en otros proyectos como punto de partida:
Haga clic en la carpeta Player en el panel de proyectos.
Crear un prefab nuevo. (Va a aparecer dentro de la carpeta Player.)
Dar al Prefab nuevo un nombre apropiado. Por ejemplo: LerpzPrefab.
Arrastre el GameObject Player a LerpzPrefab para completar el proceso.
Muerte y Renacimiento
Los personajes de un juego Plataforma tienden a llevar una vida de riesgo y Lerpz no es una
excepción. Tenemos que asegurarnos de que pierde una vida si se cae del nivel. También
tenemos que hacerlo reaparecer en un lugar seguro en el nivel por lo general llamado un "punto
de reaparecion"
Otro punto es que si Lerpz puede caerse del nivel, también es posible que los otros personajes
puedan hacer lo mismo, por lo que estos también deben ser tratados adecuadamente.
La mejor solución para esto es usar un control de colisión tipo caja (Box Collider) para detectar
cualquier objeto que caiga del nivel.
Vamos a hacerla muy larga y amplia, de modo que si un jugador intenta utilizar el jetpack
mientras cae, todavía caiga en ella. Sin embargo, Lerpz tendrá un lugar para reaparecer.
Iremos a los puntos de reaparecer en breve. En primer lugar, vamos a construir el Box Collider:
Crear un GameObject vacío.
Cambie el nombre del nuevo objeto a FalloutCatcher.
Añadir un Collider Caja al objeto.
Añadir el script Fallout Death del menú Components>Third Person Props.
Utilice el inspector para establecer los valores como se muestra en la siguiente imagen:
25
Configuración del Fallout Catcher.
El script de la muerte Fallout
Este script es corto porque simplemente delega todo el trabajo al script ThirdPersonStatus.
(Este debe ser conectado a Lerpz, pero no vamos a hacerlo justo ahora.)
El código para manejar el trigger del Collider se encuentra en OnTriggerEnter (). Esta función es
llamada por Unity cuando el Collider de Caja es golpeado por otro GameObject que tenga un
Componente Collider, como Lerpz o un enemigo.
Hay tres pruebas: una para el personaje, uno para un objeto RigidBody simple, y una tercera
prueba para comprobar si el objeto tiene un componente de CharacterController. La segunda
prueba busca si accesorios como cajas o cajones se caen del nivel. La tercera prueba se utiliza
para los enemigos, ya que estos no manejan física ordinaria.
Si el personaje golpea el Collider de caja, el código simplemente llama a la funcion FalloutDeath ()
en el script de ThirdPersonStatus de Lerpz.
Si otro objeto con un objeto Collider golpéa nuestro GameObject, simplemente lo destruimos,
de la escena, de lo contrario caerá para siempre.
Además, tenemos:
• La función de utilidad Reset () la cuál garantiza que todos los componentes estan presentes.
Esta función es llamada por Unity de forma automática al añadir el componente por primera vez.
También puede ser llamado en el Editor haciendo clic en el icono de la rueda situado a la derecha
del nombre del componente en el Inspector:
El comando de menú Reset.
26
Si tratamos de jugar el juego en este punto, Unity muestra un error porque no se sabe donde
hacer reaparecer a Lerpz. Aquí es donde los puntos de reaparición entran en juego.
Puntos de Reaparicion
Cuando el jugador muere, necesitamos un lugar seguro para que vuelva a aparecer.
En este tutorial, Lerpz volverá a aparecer en uno de los tres puntos de reaparición. Cuando Lerpz
toca uno de estos puntos, se convertirá en activo y este será en el que vuelve a aparecer, si él
muere.
Lerpz de pie en un punto de reaparicion activo.
Los puntos de reaparición son instancias del objeto prefabricadas RespawnPrefab. (Usted lo
encontrará en la carpeta del panel de Proyecto Props.)
Este Prefab es un modelo de una base de telepuerto, junto con tres sistemas de partículas
completo, un reflector y algunas otras cosas. Aquí está la estructura básica:
• RSBase contiene el modelo en sí: una base cilíndrica corta con un disco azul brillante en el
centro.
• RSSpotlight es un objeto de spotlight que ilumina con una luz azul sutil por encima de la
superficie de del modelo, dando la ilusión de que la textura es azul brillante.
‣ Si el punto de reaparecer esta activo, un mayor efecto se muestra. Este esta contenido en el
RsParticlesActive.
Sólo un punto de reaparición puede estar activo en el nivel en cualquier momento. Cuando el
jugador toca el punto de reaparecer, un objeto Collider (establecido como un gatillo) lo detecta y
dispara la activación del punto de reaparecer.
‣ Los otros tres sistemas de partículas RSParticlesRepawn1, RSParticlesRepawn2 y
RSParticlesRepawn3 son activados juntos cuando el jugador aparece en el punto de reaparecer.
27
Estos son sistemas de partículas de una sola vez. El script los activa una vez y luego restaura el
sistema de partículas RsParticlesActive una vez la secuencia ha terminado.
El prefab contiene un script, respawn, que controla el estado del punto de reaparecer.
Sin embargo, para que el juego sepa qué punto de reaparecer específico es en el que el jugador
tiene que ser devuelto al momento de morir, tenemos que organizar los puntos de reaparición en
una jerarquía en virtud de un script controlador maestro. Vamos a hacer esto ahora:
Posiciónelo como se muestra en la imagen en la página siguiente.
Cambie el nombre de esta instancia a Respawn1.
Repita los pasos anteriores dos veces más. Puede colocar estos donde los quiera o incluso
añadir más si lo desea!
El siguiente paso es crear un GameObject vacio para adicionar todos los Respawn y dar orden al
proyecto.
Cambie el nombre por RespawnPoints
Haga todas las instancias prefabricadas respawn hijos de RespawnPoints.
Posicionando el punto de reaparecer en primer lugar. (Lerpz se ha trasladado para dar claridad)
¿Cómo funciona?
Cuando se carga la escena, Unity llama a la función start () en cada instancia del Script Respawn,
donde algunas variables útiles están inicializadas y punteros a otros elementos
se almacenan en caché.
El mecanismo clave se centra en torno a esta variable estática:
Esto define una variable global llamada currentRespawn.
28
La palabra clave static significa que se comparte entre todas las instancias del script. Esto nos
permite el seguimiento de qué punto de reaparecer es el activo. Sin embargo, cuando la escena
comienza, ninguno de los puntos se activa, por lo que necesitamos establecer un valor
predeterminado para nuestra Escena. El Inspector de Unity no mostrará variables de tipo
estático nunca, por lo que el script define una propiedad inicial de Reaparición (Initial
Respawn), que debe ser establecida para cada caso.
Arrastre el punto predeterminado Reaparición a este.
Tendrás que repetir esto para todos los puntos de reaparición en la escena. (En el tutorial, el
valor predeterminado se establece en Respawn1, que se encuentra cerca de la cárcel,
directamente debajo del punto de partida del jugador.)
NOTA No es posible establecer estas propiedades directamente en el Prefab original.
Cuando un punto de reaparecer es activado por el jugador tocando su control de colisión, el
script de ese punto de Reaparición primero desactiva el punto Reaparición viejo y luego
establece currentRespawn para que apunte a sí mismo. La funcion SetActive () se encarga de
disparar los correspondientes sistemas de partículas y efectos de sonido.
La reaparición del personaje del jugador es manejado por el script ThirdPersonStatus, que
gestiona la mayor parte del estado de juego del jugador.
Los scripts de respawn también se ocupan de los efectos de sonido. Estos se reproducen como
oneshot (una sola vez), con excepción de una fuente de audio adjunto a cada uno de los Prefab
Reaparición. Este componente contiene el sonido "activo", que es un bucle. El script,
simplemente habilita o deshabilita este sonido dependiendo de si tiene que reproducir un sonido
oneshot como cuando el jugador esta reapareciendo o activando el punto de reaparicion o
tambien cuando el punto de reaparicion ha sido desactivado.
NOTA Unity hace que sea demasiado fácil añadir efectos de sonido. Cada vez que va a añadir un
asset de este tipo, considere cuidadosamente cómo se utilizará. Por ejemplo, nunca agregamos un
sonido de "reaparición desactivado" , ya que nunca lo escucharia cuando el sonido se reproduzca,
ya que es poco probable que, debido a la posición de los puntos de reaparicion estos esten al alcance
del oído uno del otro. Si usted fuera a convertir el proyecto en una partida multijugador, puede que
desee añadir un sonido y el script necesario para manejarlo.
29
Configuración de la escena
Con nuestro héroe ahora puede moverse, el siguiente
paso es darle algo que hacer ...
Primeros pasos
En esta sección veremos la construcción del mundo de juego en donde la acción tiene lugar.
En la terminología de las película, esto significa la construcción la escenografia, colocando la
utilería y los scripts que permiten a nuestro héroe interactuar con ellos.
Nuestro primer paso es preparar el escenario. El archivo del tutorial ya tiene el nivel básico de
malla creado y poblado de con una serie de items recolectables. Pondremos un poco más de
accesorios y elementos, pero la mayoría ya se ha puesto, ya que de lo contrario este seria un
tutorial mucho mas largo.
Iluminación
El nivel ya está provisto de una luz ambiente, así como muchas luces puntuales.
Estas iluminan el paisaje, el jugador, los enemigos y, en menor medida, los items.
En el caso de este proyecto, las luces fueron colocadas por el artista que modeló el nivel. La
Iluminación desempeña un papel tan importante en la creación del ambiente que es usual dejar
esto en las manos del modelador que construyó el nivel.
30
Ubicación de accesorios
El escenario básico se proporciona ya listo en el tutorial, junto con una serie de accesorios ya
existentes.
Construcción de tus propios niveles
El nivel del tutorial fue construido organizando los componentes de paisaje en Maya y después
importando el nivel a Unity. Si a usted le gusta experimentar, o incluso crear nuevos niveles, los
elementos de cada escenario se puede encontrar en la carpeta Build Your Own! En el panel de
proyectos.
Hay un gran número de celdas de combustible y colocar todos estos haría un tutorial muy
aburrido. Vamos a colocar solo algunos items para ver como se hace.
Items de Salud
Empezamos con una tarea sencilla: la adición de algunos items de salud para recolectar. Estos
son corazones que giran y brillan y le suben el nivel de salud a nuestro jugador. Estos, ya estan
definidos como prefabs en el panel de proyectos. Mire dentro de la carpeta Props y encontrará el
objeto HealthLifePickUpPrefab listo para ser usado.
Ubicación de un item de salud.
Arrastre uno a la vista de Escena y use las herramientas de posicionamiento de Unity para
ubicarlo en alguna parte en el nivel.
Repita este proceso hasta que haya colocado una media docena de estos en todo el
mapa.
Donde ponerlos depende de usted, aunque no deben ser demasiado fáciles de encontrar.
Considere cómo el jugador pueda jugar el nivel y decida cuales son los mejores lugares
para este tipo de items. Es mejor no ser demasiado generoso, o el juego será demasiado fácil.
Por último, debemos agrupar estos items en una carpeta de algún tipo para evitar saturar el
panel de la Jerarquía. Podemos hacer esto creando un GameObject vacío utilizando GameObject>
Create emtpy en el menú. Cambie el nombre de este nuevo objeto a HealthPickups y uselo para
agrupar los items de salud, como se muestra:
31
Jerarquía de items de Salud.
El campo de fuerza
El campo de fuerza.
Por el momento, el campo de fuerza no esta animado: es sólo una textura de malla estática. El
resultado es visualmente decepcionante.
Hay varias maneras de lograr un efecto visual decente, pero ¿cuál escoger? A veces una solución
simple es la mejor: sólo animaremos las coordenadas UV de la textura para darle el efecto de un
campo de fuerza de ondulación.
La animación se realiza utilizando un script corto que se encuentra dentro de Scripts>Misc en el
panel de proyectos. Se llama FenceTextureOffset y se ve asi:
32
var scrollSpeed = 0.25;
function FixedUpdate()
{
var offset = Time.time * scrollSpeed;
renderer.material.mainTextureOffset = Vector2 (offset,offset);
}
La primera línea expone una propiedad que se puede editar directamente en la interfaz de Unity
Scroll Speed. La funcion FixedUpdate () es llamada un número determinado de veces por
segundo por Unity. Utilizamos una fórmula breve ‐‐ se multiplican el valor de Scroll Speed por el
tiempo actual para definir un offset para la textura.
Propiedades bien presentadas
Cuando Unity muestra en el inspector propiedades y variables, sus nombres se ajustan para que se
vean mejor. Normalmente, esto significa simplemente buscar las letras mayúsculas en el nombre y
la inserción de un espacio antes de cada una. Además, Unity pone en mayúscula la primera letra
del nombre. Así scrollSpeed se muestra como Scroll Speed.
Cuando una textura se renderiza, la textura en sí es por lo general sólo una imagen. La propiedad
mainTextureOffset de un material le indica a Unity que debe dibujar el offset de la textura de la
imagen dentro de su espacio UV. Esto puede ser usado para producir unos resultados muy
eficaces sin recurrir a secuencias de animación complejas.
Amplie el GameObject levelGeometry para ver los distintos elementos de datos del nivel.
Tenemos que animar la cerca en el objeto impoundFence, asi que arrastre el script
fenceTextureOffset aqui.
Script para los items de recolección
En el momento Lerpz no recoge ninguno de los items del nivel. Esto se debe a que a Unity no se le
ha dicho que permita que nuestro héroe lo pueda hacer. Tenemos que añadir dos elementos a
cada item:
• Un componente de Collider,
• Un script para manejar y actualizar el Collider asi como la salud del jugador, etc
Los artículos de recolección en el panel de jerarquía todos son instancias de Prefab, que se
muestran en azul. Mediante la edición del Prefabricado original directamente, se actualizará
automáticamente todos los elementos en el juego.
Los dos prefabs que nuestro héroe puede recoger son FuelCellPrefab y HealthPickUpPrefab.
Estos se pueden encontrar dentro de la carpeta Props en el panel de proyectos.
Seleccione el objeto raíz HealthPickUpPrefab.
Use Components>Physiscs>Add Sphere Collider para añadir un Collider esfera a los
Prefabs.
33
El HealthPickUpPrefab en el Inspector.
NOTA Una script ObjectRotater ya está linkeado a la de Prefab. Esto sólo hace que el item gire sobre
el terreno y es muy simple. Vamos a ver un ejemplo más complejo en un capítulo posterior.
Los Collideres tienen dos usos: se puede golpear con otra cosa, o se puede utilizar como
desencadenantes (trigger).
Triggers
Los triggers son los componentes invisibles que, desencadenan un evento. En Unity, un trigger es
simplemente un collider, con su propiedad Is Trigger activada. Esto significa que cuando algo
choca con el trigger, va a actuar como un conmutador virtual en lugar de una entidad física.
Los Triggers enviarán uno de tres mensajes de sucesos cuando algo los activa:
onTriggerEnter (), OnTriggerStay () y OnTriggerExit ().
Mensajes de eventos de triggers se envían a cualquier script adjunto al objeto de activación, por
lo que ahora tenemos que agregar un script adecuado a nuestros Prefabs de salud:
Vaya al menú de Componentes y elija el script Pickup del submenú Third Person Props. Esto
añadirá el script de recogida a nuestro Prefab.
Por último, establezca la propiedad Ammount hasta en 3 mas o menos. Esta es la cantidad de
salud que otorga al jugador.
34
¿Cuánta Salud?
El "HUD" muestra el nivel de salud actual del jugador, la vidas, etc, sólo es posible manejar un nivel
de salud máximo de seis. ¿Qué ocurre si el jugador recoge un item de salud cuando ya tiene toda la
barra de salud completa? Esta es una cuestión de gusto, pero para el tutorial se ha optado por la
adición de una vida extra. La lógica de esto se encuentra en el script ThirdPersonStatus.
Los items de combustible se fijan de manera muy similar, con dos diferencias:
• El valor de Pickup Type debe ser FuelCell,
• El valor de Amount que es la cantidad de combustible que el item representa (1 suena logico).
Plataformas de salto
Una plataforma de salto
Las plataformas de salto son los espacios de rayas de color amarillo brillante y negro en nuestro
nivel. Estos sirven para impulsar a Lerpz en el aire. Vamos a utilizar un Collider con un script
adjunto para este fin.
En primer lugar, cree un GameObject vacío y llamelo Jump Pad Triggers. Vamos a utilizar esto
como una carpeta para guardar nuestros objetos Jump Pad Triggers juntos.
Ahora vamos a construir nuestro Prefab:
Crear un GameObject nuevo vacío.
Cambie el nombre de este objeto a JumpPad Trigger 1.
35
Añada un Box Collider. (Un Sphere Collider funcionaría en teoría, pero el Box Collider se
ajusta mejor a la forma de la plataforma de salto.)
Establezca el Collider como un Trigger.
Añada el script JumpPad.
Ese es el objeto creado. Ahora tenemos que convertirlo en un prefab:
Arrastre y suelte el game object Jump Pad en el Prefab nuevo.
Cambie el nombre de Prefab a JumpPad Trigger.
Elimine el GameObject original de nuestro panel de la Jerarquía.
Por último, active la tecla Play y pruebe el juego para asegurarse de que todos nuestros
nuevos triggers funcionan correctamente.
Una buena organización es importante si desea que su flujo de trabajo sea suave y sin problemas.
• Use instancias prefabricadas donde sea posible.
• Trate de organizar por función en lugar de tipo.
• Use GameObjects vacíos como contenedores (Objeto vacío que se crea como padre para
agrupar objetos del mismo tipo).
Usted se sorprenderá de cuantos assets se necesitan incluso para un proyecto de baja escala.
36
La interfaz gráfica de usuario
¿Cuántas vidas nos quedan?
¿Cual es la salud de Lerpz actualmente?
Es hora de un GUI.
La interfaz de usuario
Los juegos suelen tener Interfaces Gráficas de Usuario (GUI), tales como menús, pantallas de
opciones y así sucesivamente. Además, los juegos suelen tener una interfaz gráfica encima del
propio juego. Esto podría ser tan simple como un puntaje que aparece en una esquina, o un
diseño más elaborado con iconos, pantallas de inventario y barras de estado de salud.
El HUD durante el juego
Nuestro juego necesita un GUI durante el juego para mostrar la salud del jugador, vidas restantes
y el número de celdas de combustible que necesita para escapar. Los elementos gráficos ya están
incluidos en nuestro archivo de proyecto.
La interfaz gráfica de usuario se maneja dentro del script GameHUD, que utiliza el componente
de GUI para exponer los distintos elementos. Este script necesita estar conectado al GameObject
Level, que se utiliza para tener elementos especificos de la escena. (Podríamos haberlo añadido
tambien al objeto NearCamera o a su propio "GameObject GUI", esto es principalmente una
cuestión de el gusto personal en lugar de una clave de decisión del diseño del juego.)
Usaremos el GameObject Level para administrar Estados especificos del nivel y otros scripts.
El objeto GUI Skin
En Unity el sistema de GUI incluye soporte para skinning. Esto le da control total sobre la
apariencia de cada elemento de la GUI. Construir su propio contenido de la GUI Skin le permite
cambiar la forma de un botón, su imagen, su fuente, sus colores y hacer lo mismo a todos los
elemento GUI, desde cajas de entrada de texto a través de barras de desplazamiento, e incluso
ventanas completas.
Ya que nuestra GUI de juego se basa por completo en torno a imágenes gráficas, vamos a
construir el HUD usando la funcion GUI.Label (). Sin embargo, necesitamos utilizar un tipo de
letra personalizado para nuestro HUD, con el fin de mostrar las latas de combustible restantes y
las vidas.
El asset GUISkin define el 'look' de una GUI de Unity, tanto como un archivo CSS define el aspecto
de un sitio web. El objeto es necesario si es necesario cambiar las funciones que estan por
defecto. Cuando cambiamos el tipo de letra, tenemos que incluir una GUISkin en nuestra escena.
Cambie el nombre del nuevo objeto GUI Skin a LerpzTutorialSkin.
37
Vamos a utilizar el tipo de letra denominada "Fluoride", para nuestro juego. Este es el
único cambio que estamos haciendo al skin por defecto.
Arrastre el tipo de letra Fluoride en el campo “Font” del nuevo GUI Skin:
GUI Skin, estableciendo el tipo de letra.
El objeto de GUI Skin no se añade al panel de jerarquía, sino que referenciamos directamente el
GUI Skin en nuestro script GameHUD. Junto con la GUI Skin, el script GameHUD también
necesita que le digan cuales assets utilizar para construir la pantalla GUI. Estos incluyen
el asset GUIHealthRing.
La imagen GUIHealthRing
NOTA: Usted puede haber notado una serie de advertencias por parte de Unity sobre las imágenes
de que no son una "potencia de dos" de tamaño. Muchas tarjetas gráficas prefieren que las imágenes
tengan tamaños en potencias de dos, independientemente de la cantidad de los datos reales de la
imagen, ya que esto hace que los cálculos subyacentes sean mas rapidos de realizar. Las GUIs rara
vez necesitan este nivel de optimización y los assets que estamos usando por lo tanto no estan
optimizados. Si desea averiguar si las dimensiones de una imagen son potencias de dos,
simplemente ponga la imagen en la ventana y le permitirá saber si necesita dicha optimizacion.
Esta imagen se utiliza para mostrar información de salud Lerpz. El espacio a la derecha de Lerpz
muestra la imagen de sus vidas restantes, mientras que el círculo a la izquierda se utiliza para
mostrar un gráfico de su salud restante. El gráfico se crea simplemente con la superposición de
la imagen correcta de un conjunto de seis texturas 2D, llamado healthPie1 hasta healthPie6.
La imagen healthPie5 se muestra a continuación:
38
La imagen healthPie5
NOTA Estas imágenes incluyen los canales alfa para definir la transparencia y la translucidez.
Usando imágenes separadas, nos permite dibujar la imagen correspondiente al estado de salud
actual de Lerpz.
El segundo elemento de la GUI muestra el estado de la celda de combustible, la imagen es
GUIFuelCell:
La imagen GUIFuelCell
Esto se muestra en la esquina inferior derecha de la pantalla de juego y mostrará las celdas de
combustible pendientes por recuperar antes de que el nivel esté desbloqueado.
Haga clic en el GameObject Level para seleccionarlo y ver el Inspector. Usted debe
ver el componente de entrada del HUD del juego (Script).
Añada las imagenes GUIHealthRing y GUIFuelCell al script GameHUD.
Abra la entrada de Imágenes de Health Pie.
Haga clic en el "0" al lado de Tamaño. Cambielo a "6". Ahora debe ver seis elementos vacios,
con nombres del elemento 0 al elemento 5.
Abra la carpeta GUI assets en el panel de proyectos para revelar las imágenes de la salud de
pastel. Hay seis de ellas, numeradas del 1 al 6.
39
Ajustes de script GameHUD.
Si ejecuta el juego ahora, debería ver el HUD que aparece sobre el área de juego:
El HUD dentro del juego
Independencia en la Resolución .
GUI.matrix = Matrix4x4.TRS (Vector3.zero, Quaternion.identity, Vector3
(Screen.width / 1920.0, Screen.height / 1200.0, 1));
Un problema con la interfaz gráfica de usuario es su tamaño. La captura de pantalla de arriba es de un
iMac de 24 pulgadas con con una resolución de 1920 x 1200.
Es evidente que necesitamos escalar nuestro HUD dinámicamente de acuerdo con el tamaño de pantalla
actual y resolución, así que ¿cómo podemos lograr esto?
Unity incluye soporte para una matriz de transformación. Esta matriz se aplica a todos los elementos de
la GUI antes de su representación, para que puedan transformarse, rotarse o escalarse en cualquier
combinación de forma dinámica.
La línea de codigo, del script GameHUD, muestra cómo:
Si usted va a la vista de juego, desactiva la opcion "Maximize en Play" y configura la proporcion de la
pantalla a 4:3, usted verá que la interfaz gráfica de usuario se reescala para encajar.
Si quisiéramos, podríamos tener nuestro HUD girara o se volteara boca abajo. Para los menús de juego,
pantallas de alta puntuación y otros, esta es una característica útil para tener y la vamos a utilizar para
nuestras secuencias cuando se complete el nivel.
40
El menú de Inicio
Cada juego necesita un menú de inicio. Esto se muestra cuando se inicia el juego y permite que el
Jugador seleccione diferentes opciones, cargar una partida guardada y, lo más importante,
comenzar a jugar el juego. En esta sección, vamos a construir un menú de inicio desde cero.
NOTA pantallas de Splash y los menús son escenas de Unity. Así, un nivel de juego suele ser una
escena, pero una escena no es siempre un nivel de juego. Utilizamos scripts en una Escena para
cargar y ejecutar otras escenas que las unen entre sí.
Para el menú de inicio, vamos a necesitar:
• Dos botones GUI text: "Play" y "Salir".
• El nombre del juego. Esto se hizo utilizando una tipografía personalizada.
• Algo de música adecuada.
• Algun tipo de fondo.
En otras palabras, algo como esto:
El menú de Inicio.
Configuración de la escena
El primer paso es crear una nueva escena vacía.
Escriba CMD + N en Mac o Ctrl + N en la PC, para crear una, a continuación, CMD + S o Ctrl +
S para guardarla.
Nombrela StartMenu. Unity añadirá automáticamente una cámara a la escena para
nosotros, pero no hay nada para ver en este momento.
Ahora vamos a utilizar el sistema de GUI para construir un menú:
Ir al panel de proyecto y crear un archivo JavaScript en blanco.
41
En primer lugar, vamos a añadir una directiva de script de Unity . Las directivas son comandos
que proporcionan información a Unity o instrucciones adicionales acerca del script. Estos
comandos no son parte de Javascript, como tal, sino que estan destinados a Unity. Usted puede
encontrar el código de script completo en la sección de apéndice.
En este caso, queremos que Unity ejecute nuestro script dentro del editor, de modo que podemos
ver los resultados de inmediato sin tener que parar y volver a ejecutar el proyecto cada vez:
Necesitamos un enlace al asset LerpzTutorialSkin, por lo que la primera línea de código será
esta:
Vamos a necesitar un objeto texture2D para el fondo. (Vamos a poner la imagen de fondo
Aquí en el inspector)
También queremos mostrar un mensaje de "Cargando ..." cuando el jugador hace clic en el boton
"Play" botón, por lo que necesitaremos una bandera para manejar esto:
private var isLoading = false; // if true, we'll display the "Loading..." message.
Por último, llegamos a la funcion OnGUI :
function OnGUI()
{
if (gSkin)
GUI.skin = gSkin;
else
Debug.Log("StartMenuGUI: GUI Skin object missing!");
El código anterior comprueba si tenemos un enlace a un objeto GUI Skin válido . La funcion
debug.log () retorna un mensaje de error si no. (Es una buena costumbre revisar enlaces externos
datos de esta forma ya que hace mucho más fácil el trabajo de depuración.)
El fondo.
La imagen de fondo es un elemento GUI.Label configurado para utilizar la imagen de fondo como
el fondo del elemento. No tiene texto y se establece siempre en el tamaño de nuestra pantalla, por
lo que llena la pantalla.
42
var backgroundStyle : GUIStyle = new GUIStyle();
backgroundStyle.normal.background = backdrop;
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2,
Screen.height), "", backgroundStyle);
En primer lugar, definimos un objeto GUIStyle nuevo, que vamos a utilizar para reemplazar la
GUI por defecto. En este caso, sólo estamos cambiando el elemento "normal.background" para
utilizar nuestra imagen de fondo.
La funcion GUI.Label () toma un objeto Rect. Las Dimensiones de este rectángulo se derivan
de las dimensiones de la pantalla, de modo que la imagen siempre llene la pantalla. La proporcion
de la imagen también se tiene en cuenta, de modo que la imagen es recortada y / o re‐escalada
para encajar sin añadir distorsión.
Ahora llegamos al texto del título. Antes de escribir el script para esto, tenemos que echar otro
vistazo a nuestra GUI Skin y hacer una pequeña modificación a la misma:
Nuestro menú utiliza la fuente predeterminada que se define en el asset LerpzTutorialSkin. Por
el momento, el estilo predeterminado para mostrar el texto es inadecuado para un el título
principal del juego, por lo que añadiremos un nuevo GUI Style personalizado al Skin, llamado
mainMenuTitle:
Ahora vamos a añadir un estilo personalizado a nuestro GUI Skin:
Definiendo un estilo personalizado en nuestro objeto GUISkin.
43
Abra "Custom Styles" y asegurese que "Size" está ajustado a "1". Usted debe ver una entrada
"Elemento 0".
Abra "Elemento 0" y establezca sus elementos como se muestra arriba.
Por último, ahora podemos añadir el resto del código a nuestro script:
Nota: los nombres de GUI Style no son sensibles a mayusculas cuando se intenta acceder a ellos a
través de scripts. Escribir "mainMenuStyle" es lo mismo que "mainmenustyle".
Los botones.
Ahora tenemos que modificar las propiedades del GUI Button del objeto LerpzTutorialSkin para
producir un botón más interesante.
Estamos utilizando el mismo objeto GUI Skin para este menú y para el HUD del juego. Para el
HUD, sólo la fuente debe ser cambiada. Sin embargo, para los botones del menú Inicio, también
tenemos que tener una imagen gráfica detrás del botón de texto. El diseño del botón
predeterminado no se ajusta al estilo visual del juego, así que tenemos que cambiarlo.
Haga clic en el asset LerpzTutorialSkin en el panel de proyectos para abrir sus detalles en el
Inspector. Cambie a la configuración que se muestra a continuación. Ignore los otros tipos de GUI
element, que no vamos a utilizarlos:
Configuración de las imágenes de botón en el objeto de GUISkin LerpzTutorialSkin.
44
Ahora vamos a agregar el botón "Play":
Lo anterior es todo lo que se necesita para hacer y manejar el botón "Play". El código, tanto para
el rendering y la gestión de eventos esta en el mismo lugar, por lo que es más fácil de mantener.
La funcion GUI.Button () toma un objeto Rect para definir la posición del botón y su tamaño,
seguido de la etiqueta de texto.
Si el usuario hace clic en este botón, el botón de la función devuelve verdadero, por lo que puede
cargar el nivel de juego.
Hemos establecido isLoading para que sepamos que debemos mostrar el texto "Cargando ...",
luego decirle a Unity que cargue el nivel de juego.
El botón "Quit" se maneja de forma similar, pero con una prueba para garantizar que esto se
ejecuta como ejecutable independiente (o en el editor de Unity).
El paso final es el texto "Cargando ...", el cual es mostrado cuando la escena esta cargando, esto es
mas notable cuando el juego es streamed y es ejecutado en Web Player.
if (isLoading)
GUI.Label ( Rect( (Screen.width/2)-110, (Screen.height / 2) - 60, 400, 70),
"Loading...", "mainMenuTitle");
}
Botón Salir.
El botón "Salir" sólo funcionará si se está ejecutando el juego como una aplicación independiente. Si
es que se está reproduciendo en un WebPlayer, en un Widget de Dashboard o dentro del Editor de
Unity, el botón "Salir" no hará nada.
El siguiente paso es añadir algo de música.
45
Ir al panel de proyecto, abra la carpeta Sounds y arrastre archivo de audio StartMenu al
objeto MainCamera en el panel de la Jerarquía. Esto añadirá un Componente de clip de audio.
Si juega ahora en la escena, debería ver algo como esto en la vista de juego, acompañado de un
corto loop con una melodía orquestal:
El menú Inicio en acción.
SUGERENCIA La música fue creada usando loops de Apple Loops Orchestral Jam de Apple y
arregladas en GarageBand. Para usuarios de PC recomendamos el uso de Audacity.
Game Over
El pantallazo de Game Over se muestra cuando el jugador ha terminado su juego o no ha logrado
el reto. A diferencia del menú Inicio, esta escena no tiene botones: sólo muestra un mensaje de
"Game Over" más un telón de fondo, mientras que suena un jingle corto. Una vez que el jingle se
ha completado, o si el usuario hace clic en el Mouse, se carga automáticamente el "Menú de
Inicio" de la escena.
En primer lugar, crear una nueva escena y darle el nombre "GameOver"
46
Los ajustes de GameOverJingle.
No necesitamos añadir nada más a la escena con el Editor: la cámara por defecto solo será
suficiente.
El siguiente paso es construir el script (Usted puede encontrar el código de script completo en la
sección de apéndice):
Crear un asset Javascript nuevo y darle el nombre "GameOverGUI"
Abrirlo en el editor y añadir el código se describe a continuación:
Al igual que con el menú Inicio, queremos ser capaces de ver nuestra interfaz gráfica de usuario
en el editor de Unity, incluso , cuando el proyecto no se ejecuta, por lo que debemos añadir lo
siguiente:
@script ExecuteInEditMode()
Para el menú de inicio, hemos utilizado el asset GUI Skin LerpzTutorialSkin. La GUI Skin define
un montón de estilos de GUI y nos permite aplicarlos a una interfaz gráfica de usuario al por
mayor.
Una técnica alternativa es definir los objetos individuales de estilo GUI directamente. Haremos
esto para el script Game Over definiendo tres variables GUIStyle que luego podemos poner en el
Inspector, junto con dos variables que definen la escala de los elementos de texto:
Vamos a establecer estos objetos de GUI Style en el Inspector dentro de poco.
A continuación, debemos definir factor de escala del texto para nuestro mensaje "Game Over", ya
que se hizo más grande que el tamaño de fuente por defecto.
47
Vamos a dibujar este mensaje dos veces, en dos colores diferentes, para dar un efecto de sombra,
por lo que vamos a definir dos variables:
Por fin llegamos a la funcion OnGUI ():
function OnGUI()
{
En primer lugar, el fondo, se re‐escala de forma similar a la utilizada en el menú de Inicio:
La siguiente tarea es elaborar la versión de la sombra del mensaje "Game Over". Tenemos que
escalar el texto y centrarlo en la pantalla. Afortunadamente, podemos utilizar la matrix de
transformacion predeterminada para controlar la ampliación.
Para asegurar el texto aparece color oscuro, pasamos el GUI Style gameOverShadow a la función
de GUI.Label.
Guarde el archivo y pongalo en Main Camera.
Haga clic en Main Camera para ponerlo en el Inspector. Es hora de establecer las
variables ...
48
En primer lugar, el fondo de GUI Style. Esto sólo necesita la imagen
"GameOverSplashScreen" en la ranura Normal>Background, como se muestra a continuación:
Los Ajustes para el Background.
Luego, vamos a establecer texto del GUI Style Game Over como se muestra en la imagen
siguiente. (Como de costumbre, deje los otros ajustes como están.)
La configuracion para el Game Over Text.
A continuación, establezca la escala del Game Over a 1,69.
49
Ahora los ajustes de Game Over Shadow GUI:
La configuracion para el Game Over Shadow GUI.
Por último, establezca la escala del Game Over Shadow Escala a 1,61.
Ahora debería ver la GUI aparecer en la vista de juego, como se muestra a continuación:
El pantallazo de Game Over .
50
El toque final consiste en añadir un segundo script a la Main Camera que comprueba si la música
ha terminado de sonar y, de ser así, carga la escena del menú Inicio.
Crear un nuevo asset Javascript Script. Nombre que GameOverScript.
function LateUpdate ()
{
if (!audio.isPlaying || Input.anyKeyDown)
Application.LoadLevel("StartMenu");
}
Este código comprueba si el audio ha terminado de sonar, o si el jugador ha presionado una tecla
antes de cargar la escena "StartMenu".
Añadir GameOverScript a la Main Camera y listo: terminamos el GUI!
51
Adversarios
Ningún juego está completo sin adversarios.
En este capítulo, se añaden los
enemigos de Lerpz para luchar.
Contendientes
Estos dos elementos son fundamentales para cualquier juego, así que necesitamos algo para
mantener a Lerpz alerta. El trabajo del diseñador del juego es lanzar los obstáculos en el camino
del jugador, pero de una forma que sean superables. Lerpz se enfrenta a dos adversarios: los
guardias robot y las barreras láser.
Las Trampas de láser
Las Trampas láser se encuentra en los pasajes de láser y lastimaran a nuestro jugador si llega a
tocar el haz de luz. La siguiente imagen muestra dos de ellos. Los ubicaremos en los pasadizos
cortos a cada lado de la arena, en el otro extremo del nivel de la cárcel.
Lerpz se enfrenta a las trampas láser.
Los láseres suben y bajan. Si el jugador trata de pasar a través de uno de ellos, va a perder algo
de su salud.
52
Implementando las Trampas láser
Cada trampa láser es un haz de luz que sube y baja en un mismo plano vertical. Si Lerpz (o un
enemigo) llega a tocar el rayo, va a causar daños.
El rayo láser es producido por un componente de Line Renderer que figura en su propio
GameObject. Su movimiento y la lógica que lo controla esta totalmente contenida en el Script
LaserTrap. Así que vamos a construir nuestra primer trampa láser:
Cree un GameObject vacío.
Cambie el nombre a "Laser"
Agregue un componente Line Renderer (Component>Miscellaneous>Line Renderer).
NOTA No trate de colocar el láser todavía! Usted tendrá que desactivar la casilla de
"Use World Space" primero.
Añada el script LaserTrap.
Ajuste la configuración del componentes Line Renderer como se muestra. (El material del
laser se encuentra en: Particles>Sources>Materials)
Configuración de Line Renderer.
Coloque el objeto resultante en los túneles de láser. (Estos son los pasillos cubiertos en
ambos lados de la arena)
Añada un GameObject Light Point como un hijo a nuestro objeto láser.
Establezca el Point Light como se muestra:
53
Ajustes de luz del Point Light de la trampa Láser.
La luz actúa como la fuente de luz del láser y sube y baja con el láser. Esto da la ilusión de que el
rayo láser, elaborado por el Line Renderer, está emitiendo la luz.
El componente de Line Renderer
El renderizador de línea, como su nombre indica, traza líneas en un espacio 3D dentro de
nuestra escena. Contiene un arreglo que define la serie de puntos a través de los cuales la línea
sera
dibujada. La línea en sí es dibujada usando la misma técnica que el componente Trail Renderer,
lo que es ideal para el láser, rayos y otros efectos similares.
A continuación, establezca las propiedades del script LaserTrap, como se muestra:
Las propiedades del script LaserTrap.
Por último, duplique (CMD + D en Mac, o Ctrl + D), (o cree un prefab) de nuestro láser y
ponga algunos en el nivel como mejor le parezca. Se sugiere colocar cuatro en total, dos en cada
uno de los túneles.
54
Siéntase libre de variar las propiedades del script LaserTrap y experimente hasta obtener un
resultado con el que este satisfecho.
El Script Laser Trap
La clave de la trampa láser es el script LaserTrap, así que vamos a echar un vistazo más de cerca
...
Descripción general
La trampa láser es un componente Line Renderer que se mueve hacia arriba y hacia abajo gracias
al script. Este mismo script tambien controla las colisiones y dispara los efectos visuales
necesarios
En primer lugar, definamos algunas propiedades básicas de nuestra trampa láser:
• height (altura) define la amplitud de la oscilación, dictando hasta qué punto por encima y por
debajo del punto de partida el rayo láser viajara;
• speed (velocidad) define qué tan rápido se mueve el haz;
• timingOffset nos permite configurar cada objeto de trampa láser para que comience en un
punto diferente en su ciclo de oscilación;
• laserWidth define el ancho del haz de láser desde un extremo a otro;
• damage (daños) define el daño que el jugador sufrirá si se encuentra con el haz.
• hitEffect, puede ser utilizado para conectarlo a un GameObject cualquiera, que será instanciado
cuando algo le pegue al láser. Esto es más flexible que codificando el efecto en el objeto Laser
Trap y hace más fácil la reutilización de este asset en otros proyectos.
El script define dos funciones:
La funcion de Start() inicializa el componente Line Renderer, almacenando su ubicación inicial
(en el eje Y) para más tarde, y estableciendo de segundo vértice del Line Renderer para que
coincida con la posición definida por laserWidth. Esto nos permite ajustar fácilmente la longitud
del haz a que coincida con el ancho del corredor.
Ahora llegamos a la funcion principal Update (). Aquí es donde las cosas interesantes suceden.
En primer lugar, tenemos el movimiento del rayo láser para calcular. Nos limitamos a usar la
funcion Mathf.Sin (). Cogemos la hora actual usando Time.time, (que devuelve el tiempo, en
segundos, desde que el juego comenzó), se multiplica por la velocidad de animación deseada y se
añade en el valor timingOffset. Esto nos da nuestra posición a lo largo de la curva sinusoidal. Por
último, la modulamos por nuestra altura deseada y usamos el resultado como un offset de
nuestra línea base.
El siguiente paso es revisar las colisiones. El script lanza un rayo a lo largo de la ruta del laser y
comprueba si golpea cualquier GameObject que tenga un componente Collider unido a ellos.
Si chocamos con algo, revisamos si se trata de un jugador o un enemigo y, en caso afirmativo, se
envía el mensaje "ApplyDamage". Al mismo tiempo, también se instancia el GameObject hitEffect
para que realice su accion. Esta es el GameObject LaserHit, que produce un efecto de explosión
de energía:
55
Ser golpeado por un láser es malo para su salud.
Si se juega el tutorial, usted debe encontrar que Lerpz pierde un punto de salud si toca el haz del
láser.
Los Guardias Robot
Los contrincantes móviles son guardias robot, colocados estratégicamente en todo el nivel.
Cuándo Lerpz esta dentro de su rango, estos guardias le seguiran y trataran de hacerle daño.
Un guardia robot.
Los enemigos de Lerpz en el juego son los guardias robot. Podemos determinar que:
• Los Robots tendrán una IA bastante rudimentaria.
• Los robots sueltan items cuando son derribados.
• Robots reaparecerán cuando el jugador no puede verlos.
Buscar y destruir
La mayoría de la IA del juego se centra principalmente en el modelado de comportamiento y no
en la inteligencia como tal. Nuestros robots reaccionan en formas predecibles a la presencia del
jugador. Se les da una pauta para buscar y esto hace más fácil el aprender a vencer a los robots.
Los guardias robot por lo tanto tienen un patrón de comportamiento muy simple y esto se refleja
en el script de IA, EnemyPoliceGuy.
56
Idle ‐‐ En este modo, los guardias se quedan quietos, en silencio y esperan a que un intruso entre
en su rango.
Threaten -- Si un intruso entra a una determinada distancia del guardia, el sale del de modo de
espera y anuncia sus intenciones, girando su bastón de mando de una "forma amenazante".
Si el jugador se mueve fuera del rango de exploración del robot, el robot se volverá al modo idle.
Los estados antes mencionados son manejados por la secuencia de comandos EnemyPoliceGuy,
que también se ocupa del cambio entre las secuencias de animación.
Adición de los Guardias Robot
Tenemos unos cuantos de estos robots en nuestro nivel, así que ...
Busque un lugar adecuado en el nivel y los Prefabs en la escena, asegurándose de que esté en
el suelo. (El Prefab incluye un componente Character Controller. Asegúrese de que el extremo
inferior de la cápsula del Collider toque el suelo, o este ligeramente por encima de este.)
Las áreas con cercas o que son principalmente cerradas son las mejores ya que esto hace que que
sea menos probable que el robot se caiga del escenario.
Si prueba el juego ahora, podrá ver al robot ejecutando la animacion de inactividad. Ahora
tenemos que añadir algunos scripts para hacer que estos robots hagan algo más interesante.
Hay dos scrips para el robot y se adicionarán directamente al Prefab original:
Si usted juega el juego ahora, el robot debe reaccionar si se acerca demasiado a este.
Blue Sparks of Death
Si el jugador vence al robot y lo derriba, una secuencia de muerte es inicializada. Queremos que el
robot caiga en una lluvia de chispas y se quede allí hasta que el jugador este fuera del rango antes
de que se reestablezca.
Además, cuando el robot se muere, queremos que deje caer items.
En lugar de un número aún mayor de scripts, los datos de animación y otros elementos a nuestro
Prefab actual, vamos a crear uno nuevo sólo para la las chispas.
57
Divide & Conquista
Cuando nuestro robot muere, lo necesitamos que deje de reaccionar al jugador y suspenda los
scripts. Esto no es tan sencillo como parece: los scripts tienden a correr de forma independiente,
por lo que se necesita enviar mensajes y mantener una variable de estado dedicada en cada
script que debe ser revisada durante cada ciclo.
Es mucho más fácil simplemente cambiar nuestro Prefab robot por otro doble, construido
específicamente para el propósito de caerse, con adecuados efectos especiales, y script para
arrojar hasta dos items al azar.
Un robot de guardia derribado
La imagen de arriba muestra esta sustitución de Prefab en acción.
El script que ejecuta esto es EnemyDamage, Puede implementar todo lo anterior mediante la
selección del gameobject y la alteración de los valores a los componentes. Le animamos a probar
diferentes variaciones.
Items que sueltan los enemigos y Física
Los items que aparecen cuando un robot es derrotado son Prefabricados derivados de los originales
que creamos antes, pero con efectos de partículas adicionales y un script, DroppableMover, que se
ocupa de movimiento y colisiones.
El script es necesario porque el Collider está configurado como un trigger para la recolección y por lo
tanto es ignorado por el motor de física. Al item se le da una velocidad inicial y el script utiliza casting
raycasting -- una línea imaginaria hacia abajo para comprobar si el item toca una superficie. Cuando
lo hace, el script es simplemente desactivado. (Este código tiene un inconveniente: sólo comprueba
hacia abajo, en el eje Y. Así pues, el item puede terminar incrustado a medias en una pared.)
Nacimiento y optimización
El nacimiento de enemigos cuando están dentro de una distancia determinada del jugador es un
viejo truco que data de los primeros juegos de vídeo, asi, se elimina la necesidad de almacenar el
estado de cada enemigo. También podemos usar este truco para reducir la carga en el
procesador. Simplemente borrando cada robot si no es visible para el jugador, se puede evitar la
utilización de scripts e IA innecesaria.
58
Empecemos:
crear un GameObject vacío en el nivel superior del panel de la Jerarquía.
Cambiarle el nombre por CopperSpawn.
Ajustes CopperSpawn.
Vamos a necesitar varios de estos Game Objects, así que vamos a crear un GameObject parent
Para que los CopperSpawn sean sus hijos ...
Cree un GameObject vacío en el nivel superior del panel de la Jerarquía.
Cambie el nombre a Enemies.
Ahora, construya un prefab con nuestro GameObject CopperSpawn. Ponga instancias de
estos en todo el nivel.
¿Cómo funciona.
Los GameObjects CopperSpawn contienen un script que comprueba si el jugador ha llegado
Al rango previsto y, si es así, crea una instancia del Prefab Copper. Cuando el jugador
camina fuera de este rango, nuestro script automaticamente eliminara el robot de la escena.
El script que hace esto es EnemyRespawn. Las dos funciones principales son:
Start () sólo guarda en caché un enlace al transform del Game Object del jugador veremos más
adelante.
Update () En primer lugar comprueba si el jugador esta en el área y crea una instancia del robot
si es así. Si el jugador acaba de dejar la zona, se destruye el robot prefabricado.
NOTA El icono de imagen se encuentra actualmente almacenado en la carpeta [ProjectPath] /
Assets / Gizmos
59
El OnDrawGizmos () la función que muestra el icono del robot.
El código del Gizmo para el icono se muestra a continuación:
function OnDrawGizmos ()
{
Gizmos.color = Color(1, 1, 1, 1);
Gizmos.DrawIcon(transform.position, gizmoName + ".psd");
}
La funcion OnDrawGizmos () es llamada cada vez que la interfaz grafica del editor de Unity se
actualiza o se refresca, por lo que el icono será siempre visible. Para que esta funcion sepa que
imagen usar para el icono debemos…
En este ejemplo, la función dibuja una esfera utilizando spawnRange para definir su radio,
proporcionando así una representación visual de la zona en la que el robot enemigo será
instanciado; cuando el jugador se mueve fuera de esta esfera, el robot sera destruido de forma
automática .
function OnDrawGizmosSelected ()
{
Gizmos.color = Color(0, 1, 1);
Gizmos.DrawWireSphere(transform.position, spawnRange);
}
60
La funcion OnDrawGizmosSelected () muestra la esfera definida por la variable Spawn Range.
Optimizaciones Alternas
Además de la técnica anterior, Unity también ofrece las funciones OnBecameVisible () y
OnBecameInvisible (). Sin embargo, a diferencia de nuestra técnica de reaparición, las funciones
anteriores se basan en la orientación de la cámara y otras opciones en lugar de los del objeto del
jugador. Esto significa que usted verá OnBecameInvisible () llamada en un objeto, simplemente
porque la cámara a dejado de mirar hacia este y ya no es visible para la misma. Esto puede no ser lo
que que usted requiere.
Otra técnica, aún más óptima que la nuestra, es utilizar componentes como Collider de manera de
Trigger en lugar de utilizar código de script para verificar la ubicación del jugador. Unity
proporciona las funciones OnTriggerEnter () y OnTriggerExit () para este fin. Sin embargo, esto
podría no ser factible si quieres que tus scripts de reaparicion esten conectados a un objeto que
debe utilizar un collider para otros fines.
61
Audio y Toques Finales
En este capítulo, agregaremos efectos de sonido
y dos cinemas a nuestro juego.
Introducción
Cuando usted compra un CD o ve una película, el sonido que se oye siempre ha pasado a través
de una serie de etapas, la última de las cuales es conocido como el masterizado. El masterizado es
el arte de escuchar el audio en su conjunto y ajustar los niveles de volumen, filtrado las
frecuencias y cualquier número de otros trucos técnicos para hacer la mezcla final de sonido
suene lo mejor posible. A veces el proceso corrige de errores evidentes en proceso un número
musical o banda sonora, como un instrumento que está demasiado alto o suena demasiado
brusco. En otras ocasiones, el proceso sólo se utiliza para garantizar la banda sonora suene bien
atravez de el altavoz de un televisor barato sin comprometer el sonido que se escucha en un
sistema de sonido de cine en casa o home theater.
Los juegos no son diferentes: una vez que el gameplay basico está en su lugar, tiene sentido
gastar algo de tiempo modificandolo y ajustandolo hasta que sea tan bueno como sea posible.
Audio
La finalización y masterizada de audio para juegos es una tarea dificil. Los juegos son
interactivos a diferencia de otras formas convencionales de entretenimiento las cuales son
pasivas y lineales. Esto significa que usted necesita considerar cómo los assets individuales de
audio en el proyecto van a interactuar entre si, y si es necesario, realizar algunas tareas de
masterización y mezcla usted mismo. Esencialmente el masterizado es una tarea en tiempo real
que debe ser manejada dentro de la lógica del juego en sí.
En un mundo ideal, todos los desarrolladores tendrian acceso a su propio ingeniero de audio,
pero este es el mundo real, y para muchos proyectos de pequeña escala esto seria simplemente
imposible.
La consideración más importante es asegurar cada sonido en el proyecto sea coherente con
todos sus compañeros. Este es un proceso subjetivo, como algunas personas les gusta mucho el
bajo, mientras que otros prefieren sonidos de alta frecuencia, así que es una buena idea usar la
retroalimentacion de testes para obtener una mezcla de puntos de vista objetivos sobre los
sonidos de su proyecto.
Idealmente, usted necesita utilizar el audio de una sola fuente, mezclado por el mismo par de
oidos, por lo que usted consigue un sonido consistente. En el caso de este tutorial se deben
utilizar un montón de diferentes fuentes de audio, hay que estar preparado para una gran
cantidad de retoques en la configuración para lograr que los sonidos suenen bien dentro de la
mezcla. Un efecto de sonido sobresaturado(muy duro) será muy evidente para los jugadores y
62
podría llegar a ser irritante si se escucha con frecuencia. Pruebe el juego con frecuencia y este listo
para separar tiempo para realizar estos ajustes.
Notas
Unity tiene una interfaz bastante simple para el audio, pero hay algunas cosas importantes para
tener en cuenta:
• Asegúrese de que los efectos de audio tengan niveles similares. Esto hace que los niveles de
volumen y la atenuación sean mucho más consistentes. La normalización puede ayudar aquí, pero
también debe considerar cómo sus sonidos se mezclan. Demasiados efectos de sonido ruidosos
confundiran la jugador.
• Utilice efectos de sonido mono si necesita posicionar el sonido de forma realista en un mundo
3D.
• Comprima los efectos de audio utilizando el sistema de compresión Ogg Vorbis. (Unity puede
hacer esto por usted.)
• Si el juego es para web, siempre se debe comprimir tus sonidos usando Ogg Vorbis.
• Marque la casilla "Decompress on load" para sonidos cortos que se usan frecuentemente.
• Utilice sonidos en stereo solo para larga piezas musicales que no necesitan ser colocadas
espacialmente dentro de la escena. Los sonidos de esta clase siempre se reproducirán tal como
son, en el volumen de audio predeterminado de el Audio Listener.
Agregando sonido a Lerpz Escapes!
Ya hemos añadido algunos pocos efectos en el juego. En este capítulo vamos a añadir un poco
más de audio a nuestro juego y completar el proceso.
Para muchos géneros de juegos, los efectos de sonido se pueden obtener a partir de fuentes
reales, o sacados de una biblioteca de efectos de sonido. Sin embargo, Lerpz Escapes! necesita
algunos efectos de sonido que no pueden obtenerse tan fácilmente. Apuntando con un micrófono
en una nave espacial que pasa o un conveniente guardia robot no es una opción, así que
tendremos que pensar de manera creativa acerca de estos.
No vamos a agregar todos los efectos de sonido posibles para el juego en este capítulo, sólo lo
suficiente para demostrar las características de audio de Unity. Una vez que haya leído este
capítulo, usted será capaz de añadir efectos de sonido adicionales por su cuenta.
La lista completa de efectos de sonido que necesita el juego es:
El jugador:
• Sonidos Caminar / Correr.
• Sonido de ataque.
• Sonido de golpe recibido.
• Sonido de muerte de personaje.
• Sonido de propulsores del Jetpack.
La Guardia Robot:
• Sonido de ocio.
• Sonido de ataque.
• Sonido de golpe recibido.
• Sonidos de Muerte / Explocion;.
Items:
• Sonido de cogida de pila de Combustible.
• Sonido de cogida de item de salud.
Los sonidos ambientales:
• Un sonido largo en loop para dar una sensación de ambiente.
• Un sonido de zumbido para las almohadillas de salto.
Cerca de la nave espacial:
• Sonido de activacion.
63
• Sonido de apagado.
La nave espacial:
• Sonido de despegue para reproducir en el cinema.
Ya hemos agregado algunos efectos de sonido a nuestro juego, pero todavía tenemos que añadir
más de quince más. Algunos de estos sonidos fueron tomados de el mundo real, como los pasos
del jugador y los propulsores del jetpack. Algunos de los sonidos de otros son tambien sacados
del mundo real pero reacondicionados para nuestras necesidades.
Estos sonidos pueden encontrarsen en casi cualquier biblioteca de efectos de sonido. GarageBand
de Apple, Logic Studio 8 y Soundtrack / Soundtrack Pro incluyen este tipo de sonidos y estas
bibliotecas fueron la fuente de la mayoría de los efectos de sonido en este tutorial. Muchos de
estos sonidos estan disponibles en linea, muchas veces gratis!
Sonidos de Ambiente
Nuestro juego se desarrolla en un medio ambiente por encima de las nubes con una
impresionante vista de los planetas cercanos. Este lugar fuera de este mundo necesita una
adecuada ambientacion sonora para mejorar la sensación de inmersión en el juego.
El proyecto incluye un loop de sonido ambiental llamado sceneAtmosphere.
La muestra se agrega al objeto Near Camera en el panel de la Jerarquía.
Arrastre y suelte el efecto de sonido dentro de el objeto Near Camera. Unity creara
automaticamente un componenet Audio Source.
Ajuste su configuración como se muestra a continuación:
Agregar el sonido sceneAtmosphere al objeto Near Camera.
64
El componente Audio Source incluye los controles básicos que nos permiten decir cómo Unity
maneja el efecto de sonido ya sea a través de el Inspector o a través de scripting.
En este caso, activamos la opcion Play On Awake para que el sonido empieze a reproducirse
automáticamente. El nivel de volumen es deliberadamente bajo ya que es un sonido de ambiente
de fondo y no queremos distraer la atención de los otros sonidos en el juego.
Echemos un rápido vistazo a lo que los valores restantes significan:
El Pitch define la rapidez con la que el sonido se reproduce , siendo 1 la velocidad normal.
El algoritmo usado es basico, similar a una grabadora; un valor de 2 aquí reproduciria la muestra
a el doble de su velocidad normal.
SUGERENCIA El ajuste de Pitch es útil para efectos de sonido cortos ya que usted puede ajustar el
valor ligeramente con cada reproducción para añadir variedad a los sonidos. Es ideal para
disparos, los láseres y los pasos y evita así la necesidad de tener que crear múltiples efectos de
sonido.
Despues estan los valores que definen el rango de volumen de el sonido. Si quisiéramos que el clip
fuera inaudible cuando estamos muy lejos de su fuente, Min Volume se establece en cero.
Como su nombre indica, Max Volume es el máximo volumen del sonido. Podríamos pararnos
sobre la fuente de sonido y no se escucharia mas duro que este valor.
Luego viene el Rolloff factor, que determina lo rápido que el volumen del sonido cambia relativo
a la distancia del oyente. Un valor más pequeño significa que el sonido sera audible sobre una
distancia mayor. Esta configuración es clave para asegurar un comportamiento foneticamente
realista en el juego.
NOTA Es importante asegurarse de sonidos en loop esten diseñados para un loopeo limpio, de lo
contrario lo más probable es que escuche un clic o pop cada vez que se reinicia la reproducción
desde el comienzo de la muestra. La mayoría de los editores de audio incluyen una funcion llamada
"Find zero crossings " para este fin.
Plataformas de salto
Cuando se construyó el Prefab JumpPad, ignoramos su efecto de sonido. Ahora vamos a agregar
uno. Pero, ¿cómo vamos a reproducirlo?
Por suerte, el script del JumpPad ya tiene soporte para un efecto de sonido. Si abre el script en el
editor, verá el código de reproducción de aquí:
...
if (audio)
{
audio.Play();
}
...
La variable de audio no parece estar definida en el script, así que ¿dónde viene esta?
Viene de el mismo Unity. Esta es una variable de conveniencia, una entre un número de tales
variables, que simplemente apunta hacia el componente de Audio Source conectado a el
GameObject en el cual se encuentra el script. Como no hemos añadido uno de estos
Componentes, la variable audio será nula, por lo que el script se salta la reproducción.
65
Haga clic en una de las instanias de plataformas de salto en al escena para desplegar el
inspector de este GameObject.
Arrastre el efecto de sonido jumpPad hacia el inspector. (Esto creará automáticamente
un componente de Audio Source.)
Aplicar el cambio a la Prefab original, así que todas nuestras plataformas de salto puedan
compartir el mismo efecto de sonido.
Experimente y ajuste la configuración de la fuente de audio hasta que esté satisfecho con el
efecto de sonido.
Items
Los items son los más fáciles de tratar. Estos efectos de sonido son pickupFuel y pickupHealth
para las céldas de combustible y items de la salud, respectivamente. La incorporación de estos
efectos es la simplicidad misma: el script de recogida ya tiene soporte para audio, sólo
necesitamos arrastrar el efecto de sonido relevante hacia el espacio correspondiente para cada tipo
de item.
Configuración de el efectos de sonido de el prefab fuelCellPrefab.
Aplicar el mismo proceso para el item de la Salud, utilizando el ejemplo de pickupHealth.
66
Sugerencia Puede agregar el efecto de sonido directamente a el prefab para ahorrar tiempo.
Si usted juega el juego ahora, cada item debera reproducir el sonido apropiado cuando este se
recoja.
La cerca
El campo de fuerza que rodea la nave espacial debería hacer un zumbido, ruido de efervescencia
mientras está activo.
El efecto de sonido se llama activeFence.
vaya al panel de jerarquía, despliegue levelGeometry y encontrara el objeto
impoundFence.
Por último, cambie la configuración de Audio Source de la siguiente manera:
Ajustes Audio Source del objeto cerca.
El Personaje
Lerpz por si solo no hace ningún sonido en el momento. Adición de efectos de sonido tiene
sentido, pero ¿cuáles?
Los efectos de sonido que vamos a aplicar en este tutorial son:
• Un sonido de puñetazo.
• Un sonido de "golpeado", se reproducirá cuando Lerpz es golpeado por un robot.
• Un efecto de sonido para los propulsores del jetpack.
• Un sonido para que suene cuando el jugador muere y renace.
(El efecto de pasos se deja como ejercicio para el lector.)
Estos sonidos seran reproducidos por nuestros scripts.
El Puñetazo.
El movimiento de puñetazo y la animación son manejados por el script Third Person Character
Attack. Una propiedad para el efecto de sonido es expuesta por el script en el inspector.
67
Establezca la propiedad Punch Sound como se muestra a continuacion:
Efecto de sonido de puñetazo de Lerpz.
El Script reproduce este sonido con el siguiente código:
if (punchSound)
audio.PlayOneShot(punchSound);
Este fragmento de codigo comprueba si un efecto de sonido para el puñetazo se ha facilitado a el
script. Si es así, que usa la funcion PlayOneShot () para reproducir el sonido. Esta función crea un
GameObject temporal con un componente de fuente de audio, lo agrega a la escena y lo
reproduce. Cuándo el efecto de sonido se termina, el GameObject es retirado de la escena.
NOTA Mientras que el juego se está ejecutando, verá estos sonidos aparecer brevemente en el panel
de la Jerarquía. Este comportamiento es normal.
Sonidos de golpeado y grito
El script Third Person Status maneja dos efectos de sonido: el que reproduce cuando Lerpz es
golpeado por un enemigo, y el que reproduce cuando Lerpz muere (justo antes de que renasca o
el juego termine). Ambos efectos de sonido son manejados de la misma manera como el efecto de
sonido "lerpzPunch” que agregamos anteriormente.
Añada los sonidos LerpzStruck y LerpzScreamSFX como se muestra a continuación:
68
Agregar los efectos de sonido a las variables Struck sound y Deatrh Sound.
El Jetpack
El jetpack usa un efecto de sonido en loop, en lugar de un oneshot, así que vamos a añadir el
efecto de sonido a el GameObject del Player directamente como un componente de fuente de
audio. El controlador de partículas de el Jetpack creará automáticamente un componente de
fuente de audio vacío, pero tenemos que agregar el archivo de audio a el mismo:
Arrastre el archivo de audio thrusterSound hacia el componente de fuente de audio dentro
de el GameObject del Player.
Asegúrese de que la configuración de fuente de audio sea como se muestra:
Jetpack ajustes de audio
69
Hay dos secciones de script para controlar este efecto de sonido, los cuales están en el script
Jet Pack Particle Controller. La primera sección va en la función start () e inicializa el
componente fuente de audio:
audio.loop = false;
audio.Stop();
El segundo bloque está más abajo en la misma función:
if (isFlying)
{
if (!audio.isPlaying)
{
audio.Play();
}
}
else
{
audio.Stop();
}
SUGERENCIA La variable de audio es creada por Unity y apunta siempre a el componente de
AudioSource en el GameObject.
Este código es autoexplicativo.
La necesidad de probar si el efecto de sonido ya está reproduciendose es debido a que la función
Play () siempre empieza a reproducir el efecto de sonido desde el principio,
independientemente de si ya está reproduciendose. Esto significa que escuchariamos el sonido
entrecortado ya que Unity reiniciaria repetidamente a la muestra de sonido cada vez que la
funcion Play () es llamada.
Robot Guardia
Estos personajes tienen una serie de scripts algunos de los cuales también tienen muestras de
audio como de propiedades.
Además, cada robot guardia tiene un componente de fuente de audio.
A diferencia del jugador, que utiliza su componente de fuente de audio exclusivamente para el
sonido del jet pack, el script EnemyPoliceGuy utiliza el componente de fuente de audio del
Prefab Copper para múltiples sonidos loppeados, cambiando entre ellos cuando sea necesario.
if (idleSound)
{
if (audio.clip != idleSound)
{
audio.Stop();
audio.clip = idleSound;
audio.loop = true;
audio.Play();
}
}
Un ejemplo el código utilizado para lograr esto se muestra a continuación:
70
El ejemplo de arriba se puede ver en la parte superior de la funcion idle () en el script
EnemyPoliceGuy . La llamada a audio.Stop () es importante ya que el intercambio de una
muestra de sonido mientras se está reproduciendo puede tener resultados impredecibles.
Para añadir los efectos de sonido:
Seleccione el Prefab Copper en el panel de proyecto para visualizar sus propiedades en el
Inspector.
Agregue el mismo effectto de sonido a la propiedad Idle Sound en el componente script
EnemyPoliceGuy.
El sonido MetalHit se reproduce en la funcion ApplyDamage () dentro de el script
EnemyDamage. El código que hace esto se muestra a continuación:
if (audio && struckSound)
audio.PlayOneShot(struckSound);
Al igual que con el jet pack, la variable audio que usamos aquí es en realidad una variable de
acceso directo creada por Unity. Es el equivalente a llamar la funcion
GetComponent(AudioSource).
NOTA El mismo truco se usa para algunos de los efectos de reproducción de sonido.
71
Copper Prefab ajustes Inspector después de añadir los archivos de audio.
Cut Scenes
Los cutscenes o cinemas proporcionan un medio útil para tener al tanto al jugador de un evento
en la historia. En este tutorial tenemos 2 cutscenes.
La primera ocurre cuando el jugador se las arregla para recoger todas las pilas de combustible
necesarias para el nivel, lo cual desbloquea la nave espacial. Esta escena aparece en un picture‐
in‐picture o recuadro, de modo que el jugador puede continuar jugando mientras la secuencia se
reproduce.
Una de las razones muy pragmáticas para no usar toda la pantalla para esta escena es que de otro
modo tendría que congelar todos los elementos de juego de los robots, el jugador, controles, etc,
mientras la escena se reproduce, porque el jugador quedaria ciego hasta que la escena termine.
La segunda escena se produce cuando el jugador toca la nave espacial después que la cerca ha
sido desactivada. Esta escena se reproduce en pantalla completa, vemos la nave espacial
despegando y volando hacia la libertad antes de pasar a la secuencia de Game Over.
Echemos un vistazo a la primera escena en detalle ...
72
Desbloqueo de la cerca
Nos topamos con la cerca por primera vez cuando agregamos animaciones a esta misma , en este
capitulo le agregamos sonidos, ahora vamos a animarla.
Pero primero, tenemos que asegurarnos de hacer esto cuando hemos recogido todas nuestras
latas de combustible
(Usted puede encontrar el código de script completo en la sección de apéndice):
Abra el script ThirdPersonStatus y busque dentro de el la funcion FoundItem ().
Después de el bloque de comentarios, agregue las siguientes líneas de código. (Asegúrese de
que insertar antes de la llave de cierre de la función '}' o no funciona!)
if (remainingItems == 0)
{
levelStateMachine.UnlockLevelExit(); // ...and let our player out of the level.
}
Guardar el script.
En la parte superior de el script, agregue el siguiente código:
NOTA El código anterior incluye variables que necesitaremos para la segunda escena también.
A continuación, añada la siguiente línea de código de script a la funcion Awake ():
levelGoal.GetComponent (MeshCollider). isTrigger = false;
Ahora, para la secuencia de desbloqueo.
Agregue la siguiente función a el script LevelStatus.
function UnlockLevelExit()
{
mainCamera.GetComponent(AudioListener).enabled = false;
73
Unity soporta sólo un componente de escucha de audio en la escena.
Normalmente esto se adjunta a la cámara principal en la escena, pero estamos utilizando
múltiples cámaras en nuestra escena, por lo que tenemos que asegurarnos de que sólo tengamos
un componente Audio Listener(escucha de audio) activo en cualquier momento. Queremos
escuchar el efecto de sonido de “fence disabled” (cerca desactivada) , así que activaremos
brevemente el componente de escucha de audio de la camara de nuestro cutscene aquí.
A continuación, debemos activar el vídeo de la cámara y activar su componente de escucha de
audio:
unlockedCamera.active = true;
unlockedCamera.GetComponent(AudioListener).enabled = true;
La cerca tiene un efecto de sonido en loop asignado a ella. Tenemos que detener la reproduccion
de el sonido ahora:
exitGateway.GetComponent(AudioSource).Stop();
Ahora podemos empezar a reproducir nuestro sonido de "cerca desactivada" :
if (unlockedSound)
{
AudioSource.PlayClipAtPoint(unlockedSound,
unlockedCamera.GetComponent(Transform).position, 2.0);
}
Con nuestro efecto de sonido reproducioendose, podemos iniciar la secuencia de animación.
Haremos esto de proceduralmente mediante el uso de código de script para lograr la animación.
Las siguientes líneas realizan esta secuencia. La primera línea añade un retraso antes de el
comienzo de la secuencia para darle tiempo a el jugador de fijar su atención a la secuancia.. (He
dejado los comentarios en su lugar para que pueda seguir la secuencia de animación):
yield WaitForSeconds(1);
levelGoal.GetComponent(MeshCollider).isTrigger = true;
74
Por último, hacemos una pausa de unos segundos para que el jugador tenga tiempo para ver los
resultados, antes de apagar la cámara de nuestra escena y restaurar el componente de escucha de
audio a nuestra NearCamera:
La creación cámara para el cutscene es nuestra próxima tarea. Esto es sólo otro Camera
GameObject, exactamente como la que hemos estado utilizando en el juego en sí. Vamos a
configurarlo:
Añadir una nueva cámara a la escena.
Cambiarle el nombre a CutSceneCamera1
Asignarle spaceShip en a el script SmoothLookAt para que el script sepa para donde necesita
apuntar la camara.
Establezca las propiedades restantes como se muestra:
CutScenCamera1 propiedades.
75
Esta cámara debe ser configurada para mirar hacia la plataforma donde se encuentra encerrada
la nave, mostrando claramente la cerca. La configuración que se muestra arriba debería ser una
buena aproximación, pero no dude en modificarla a su gusto:
Posicionamiento de CutsceneCamera1.
A continuación, ajustar la configuración de la cámara CutSceneCamera1 así:
Configuración del el componente Camera de CutSceneCamera1 .
La cámara debe ser desactivada por defecto. Será activada por nuestros scripts, pero no
queremos que renderize nada hasta que el script no le indique lo contrario. La descativación de la
cámara es muy sencilla:
76
Descative la casilla situada junto a Cut Scene Camera 1, a la derecha en la parte superior de el
inspector.
Además, ajuste la configuración de Normalized View Port Rect como se muestra arriba. Estos
definen la posición en la cual se dibujara la camara para que aparezca en la parte superior
derecha de la pantalla. El parametro Depth tambien se establece a 10, que es mayor que el Depth
de Near Camera para que la camara se dibuje sobre el resto de las camaras.
Necesitamos poner a prueba la secuencia, por lo que debemos establecer las propiedades de el
script LevelStatus como se muestra a continuación:
Configuración de las propiedades de el script LevelStatus.
El objeto spaceship es el modelo de nave espacial .
TIP he temporalmente establecido el valor de la propiedad Items Needed a 2 en la imagen de
arriba. Esto me permite probar la escena con tan solo recolectar dos latas de combustible en lugar
de perder tiempo recolectando el resto por todo el nivel. Recuerde restaurar a un número mayor
como 20 cuando hallamos terminado.
Si usted juega el juego ahora, debería ver el cinema aparecer tal como se muestra a continuación.
Nuestro primer cinema en acción.
NOTA El contador de cuadros por segundo esta visible tanto en la camara principal como en la del
cinema, su funcionamiento e implementacion esta cubierto en el capítulo sobre la optimización.
El último cinema es un poco más complejo. Necesitamos que la nave espacial despegue y salga
77
volando. Podemos hacer esto utilizando scripting, pero es mucho más fácil utilizar un
AnimationClip para algo asi:
Haga clic en el modelo de nave espacial dentro de la cerca. (O haga clic en él en el panel de
jerarquía)
Agregar el AnimationClip “ShipAnimation” de la carpeta de Animations en el panel del
proyecto y añadirlo al objeto spaceShip (nave espacial).
Si usted a juega el juego ahora vera la nave despegar. Sin embargo, sólo queremos que la nave
despegue, cuando el nivel este completo. Vamos a hacer esto con un script en un minuto. Sin
embargo Unity, por defecto, supone que las animaciones se reproducen de forma automática. No
queremos esto, así que, con el juego en Stop:
Deshabilitar la opcion "Play Automatically" del componente de Animación de la nave
espacial.
Ajustes de animación de el objeto nave espacial.
El siguiente paso es crear la camara para nuestro segundo cinema:
Crear un nuevo objeto de tipo camera.
Cambiarle el nombre CutSceneCamera2.
Posiciónela en la parte superior del edificio donde se encuentra la nave, como se muestra:
78
Posicionamiento CutSceneCamera2.
No te preocupes por la dirección que apunta: sólo estamos interesados en su ubicación. El
script que agregaremos se encargará del resto.
Al igual que con CutSceneCamera1, también tenemos que garantizar que esta se este
desactivada por defecto, pero los valores restantes son un poco diferentes, como se puede ver en
la imagen. La diferencia clave es que esta cámara tiene que dibujarse en toda la pantalla, en lugar
de aparecer en la esquina, por lo que las propiedades de Normalized Viewport Rect son
configuradas para tomar esto en cuenta.
Ajustes para CutSceneCamera2.
79
Ahora para la el cinema. Esto es un poco más complicado que nuestro primer cinema porque el
mensajes utilizados para desencadenar la escena deben ser transmitidos a lo largo de una
cadena:
Todo incia cuando el jugador toca el modelo de nave espacial. (Si el primer cinema ha
transcurrido, el modelo de nave espacial está actuando como un Trigger en lugar de un objeto
sólido).
El modelo de nave espacial por lo tanto necesita un script adjunto a la misma para hacer frente a
este evento:
Crear un nuevo script de tipo JavaScript.
Cambiarle el nombre HandleSpaceshipCollision.
Agregue el código siguiente a el script (Usted puede encontrar el código de el script
completo en la sección de apéndice):
Todo el código de arriba es para probar si el jugador ha tocado la nave espacial y, de ser así,
llame al la funcion LevelCompleted () en el script ThirdPersonStatus del Jugador.
Añadir el script al objeto spaceShip.
La funcion LevelCompleted() de el script ThirdPersonStatus es aún más corta y hace algo muy
similar.
Agregue la siguiente función a el script ThirdPersonStatus:
function LevelCompleted()
{
levelStateMachine.LevelCompleted();
}
80
function LevelCompleted()
{
En primer lugar, tenemos que hacer el mismo intercambio de Audio Listener que hicimos para
nuestro primer cinema:
mainCamera.GetComponent(AudioListener).enabled = false;
levelCompletedCamera.active = true;
levelCompletedCamera.GetComponent(AudioListener).enabled = true;
A continuación, queremos dar la ilusión de que el jugador está dentro de la nave espacial, por lo
que vamos a esconderlo. Para ello, vamos a enviar un mensaje de "HidePlayer" a el script
ThirdPersonController del jugador. La función desactiva el renderizado de que el jugador para
que se haga invisible:
playerLink.GetComponent(ThirdPersonController).SendMessage("HidePlayer");
Sólo para estar en el lado seguro, también trasladaremos físicamente al jugador a una posición
que sabermos debe ser segura. (Los robots no comprueban si el jugador es visible o no, y están
aún en funcionamiento.) En este caso, sólo tendremos que mover el jugador 500 unidades hacia
arriba, lo cual debe ser lo suficientemente lejos de cualquier peligro inmediato.
A continuación, vamos a reproducir el sonido de nivel completado. En este caso, es el sonido de la
nave espacial que despega:
if (levelCompleteSound)
{
AudioSource.PlayClipAtPoint(levelCompleteSound, levelGoal.transform.position,
2.0);
}
Ahora empezamos a reproducir la animacion de la nave y esperamos a que termine:
levelGoal.animation.Play();
Y, por último, cargamos la escena "Game Over":
81
Application.LoadLevel("GameOver"); //...just show the Game Over
sequence.
}
Ahora debemos asegurar que el modelo de nave espacial no este configurado como un trigger
cuando nuestro nivel inicia, y también asegurar playerLink está apuntando a el GameObject
Player. Vamos a definir la variable dentro de una función Awake () en playerLink, que será
llamada automáticamente por Unity cuando se carga el script.
Cambiar el Awake () para como vemos en el script de abajo . Debería estar ubicado justo
encima de la primera función en LevelStatus.
Finalmente, debemos establecer las propiedades de nuestro script, como se muestra:
La configuración final de las propiedades de el script de Level Status.
El resultado, al recoger todas las latas de combustible y saltar a la nave espacial, debe verse como
esto:
82
¡Misión cumplida! Nuestro héroe se marcha para nuevas aventuras.
El siguiente capítulo se cubre técnicas de optimización que podemos usar para mejorar el
rendimiento de nuestro juego.
83
Optimización
Es necesario optimizar nuestro juego para que pueda
correr en maquinas del mayor rango possible de
especificaciones tecnicas.
Estamos ahora en la etapa final. La optimización es algo que se hace cerca del final de un
proyecto, una vez todos los elementos están en su lugar y definidos. ¿Qué, dónde y cómo
optimizar su proyecto depende en gran medida de el diseño de su proyecto y el contenido,
por lo que este capítulo es principalmente un debate sobre los tipos más comunes de
optimización.
¿Por qué optimizar?
Los proyectos de Unity usualmente estan dirigidos a equipos de modesto rendimiento con el fin de
llevar al mayor numero de usuarios.
Por esta razón, debemos considerar la optimización de nuestros proyectos para la versión final.
En nuestro caso, ya hemos optimizado los robots enemigos, haciéndolos materializarse sólo
cuando esten en rango del jugador. Sin embargo, la representación de la escena puede ser algo
lenta y esto vale la pena examinarlo más a fondo.
Optimización de Rendering: Monitoreo de Frames Per Second
La mejor manera de determinar si el juego necesita ser optimizado es averiguar el numero de
cuadros por segundo que nuestro equipo puede presentar cuando el juego se esta ejecutando. Cuanto
menor sea el número, más lento el juego se está ejecutando.
Usted puede haber notado un número o las letras "FPS", en algunas de las imagenes en este
tutorial. Esto es porque un script importante, pero afortunadamente muy corto, se esta
ejecutando lo cual examinaremos ahora:
El script se llama FPS y se puede encontrar en la Carpeta Scripts‐>GUI del panel de proyecto.
El script está bien documentado, por lo que no esta cubierto en detalle aquí, aparte de alclarar
que se requiere un componente de GUIText en el objeto al cual agregamos el script.
Con este contador FPS, es más fácil obtener una buena idea de donde hay necesidad de hacer
optimizaciones.
NOTA El script FPS puede reportar un numero mas bajo en modo de edicion que en el proyecto
compilado, esto se debe a que el editor tiene que hacer mucho trabajo adicional para ejecutar el
juego. Para una lectura mas exacta compile el juego y ejecutelo como standalone.
84
Pantalla de Estadísticas
El boton "Stats" arriba de la vista de juego. Si lo presionamos podemos obtener algunos
indicadores adicionales en nuestro juego, que pueden ayudarnos a determinar si hay poblemas de
numero de poligonos o otra complejidad por resolver.
El panel de Estadística en acción.
Estas estadísticas se basan en lo que la cámara esta mirando, por lo cual, lo que se mueva
alrededor de la escena puede cambiar muchas de las estadísticas. Los elementos más
importantes son:
Draw Calls
El número de pasadas de dibujado. Puede ser necesario dibujar algunos elementos varias veces:
las sombras, múltiples cámaras, dibujando las texturas, luces de pixel, y más. Shaders complejos
también pueden incrementar el numero de pasadas, especialmente si se trata de reflexión o
refracción.
Tris
Número de triángulos que se están dibujando.
Todos los modelos 3D se construyen a partir de triángulos. El menor número de los triángulos,
más rápido se va a dibujar. Objetos curvos generalmente un usan más triángulos que objetos con
formas rectas.
Verts
Número de vértices que se esta enviando a los chips gráficos.
Un vértice es un punto en el espacio 3D. Mientras mas vertices se puedan compartir entre
triangulos, más triángulos se puede hacer y por lo tanto más complejo puede ser el modelo.
Used Textures
número de texturas necesarias para dibujar lo que ves.
Los materiales pueden utilizar una o más texturas, dependiendo de cómo se define el material y
el shader que está utilizando. El shader define cómo se combinan las texturas, producir efectos
tales como bump mapping, gloss, reflexión y refracción.
TIP Los sistemas de partículas utilizan dos triángulos por cada partícula, y al menos una textura.
(Texturas suelen ser compartidos por todas las partículas en un sistema de partículas.) Es muy
fácil dejarse llevar por esos efectos, pero debe tener cuidado de no exagerarse.
85
Render Textures
el número de cámaras dibujando a un Render Texture en lugar de directamente a la pantalla.
Esto no es tan simple como uno pudiera esperar ...
Render textures se utilizan para conseguir una serie de efectos, como los efectos de
postprocesado, una pantalla de circuito cerrado de televisión que muestra otra área de un nivel, o
para producir una reflexión en el agua, de un espejo o los efectos de refracción de vidrio. Además,
la mayoría de las sombras también se producen usando esta técnica, por lo que no
necesariamente se ven cámaras adicionales en el Scene View.
Optimización de Rendering: Sistema de dos camaras
Si has jugado con el proyecto terminado, te habrás dado cuenta ahora que hay, de hecho, dos
camaras: una cámara cercana (Near Camera) y una cámara lejana (Far Camera). Este sistema
reduce la cantidad de dibujado necesario para cada frame. La camara cercana dibuja todo dentro
de un rango cercano, en este caso, 0,4 a 50 unidades. La camara lejana dibuja de 50 unidades a
alrededor de 500 unidades. Sin embargo, sólo dibuja un subgrupo de objetos en la escena. El
subgrupo se define por capas. Cada objeto de la escena se le da una capa para vivir. La camara
cercana dibuja todos los elementos cercanos, independientemente de su capa, pero como se
puede ver en la pantalla de abajo, la cámara lejana se le ha instruido a ignorar objetos en las capas
“cameraTwo"o"cameraTwoIgnoreLights ". También nos gustaría ignorar las latas de combustible
y los items de la salud. Estos estan en la capa "noShadow", de modo que también está desactivada
para esta cámara.
Nota Si desactiva capa "noShadow" también significa que dibujara el jugador tampoco, esto está
bien ya que es poco probable que el jugador este tan lejos de la cámara cercana.
Los Parámetros de culling Mask de la cámara lejana.
NOTA La cámara lejana tambien es la encargada de dibujar el skybox . (Véase la configuración de
clear flags en la imagen de arriba.). La configuracion de clear flags de la camara cercana esta en
86
“depth only”, de modo que su contenido se superpone a la de la cámara lejana. El contenido de la
cámara lejana se representa en primer lugar.
Esta selección se define por la propiedad de culling mask en el componente de la cámara.
Capas seleccionadas son dibujadas; capas deseleccionadas no son dibujadas.
Usted puede ver esta optimización en acción con los guardias robot y los items. Si usted se
mueve hacia uno de estos elementos, podrás ver que el paisaje que lo rodea es siempre dibujado,
mientras que el elemento en sí mismo aparece cuando esta relativamente cerca al jugador.
87
El Fin del camino.
Sugerencias para mejorar
Este juego se ha dejado deliberadamente sin terminar. Tenemos un menú muy básico de inicio,
una pantalla de game over y el ultimo nivel del juego, podria tener mas niveles. ¿Cómo podría ser
mejorado?
Arreglando los errores dejados deliberadamente
Sí, hay algunos problemas menores con el juego tal como está. Estos han sido deliberadamente
dejados en su lugar para darle al usuario oportunidad de perfeccionar sus habilidades. Ellos son:
• Si usted mata a un robot, pero renace cerca antes que el jugador se haya movido fuera de rango,
un nuevo robot aparecerá, pero el viejo se mantendrá.
• Las Trampas de láser no empujan a el jugador, por lo que es posible perder toda la vida con
bastante rapidez.
Ambos pueden ser resueltos mediante la aplicación de lo que has aprendido en este tutorial.
Más niveles
El panel de proyecto incluye una carpeta "Build your own" que contiene todos los assets
individuales utilizados para construir el nivel, por lo que añadir nuevos niveles no debería ser
difícil.
Usted tendrá que utilizar DontDestroyOnLoad () de modo que pueda llevar la información de
estado del juego entre los niveles como la puntuación actual, la vida restante, etc.
Más enemigos
El juego sólo tiene un enemigo, los guardias robot. Por qué no añadir un poco más? Esta es una
buena manera de asegurarse de que han entendido la animación y los aspectos de la IA. También
le ayudará a obtener una sólida comprensión de la construcción de modelos y la importación de
ellos en Unity.
Añadir marcador
El juego carece de un sistema de puntuación. Añadir uno no es difícil, pero añadiendo efectos
visuales cuando el jugador hace algo digno de aumentar su puntuación puede ser tan difícil como
usted quiera. (Y, por supuesto, usted desea hacer un seguimiento de los puntajes entre escenas.)
Añadir un sistema de puntaje en red
¿Qué mejor manera de presumir que subir tu mejor puntuación a una central de servidor para
que todos puedan ver tu grandeza? Esta es una buena manera de envolver su cabeza en torno a
conceptos básicos de redes.
Añadir soporte multijugador
88
Añadiendo soporte para juegos en red multijugador es probablemente una de las cosas más
difíciles que usted puede hacerle a cualquier juego. Naturalmente, Unity puede servir también de
ayuda, pero usted tendrá que familiarizarse mucho con scripting. Esta es una buena mejora para
un nivel avanzado.
Para leer más
El primer lugar para buscar más información es, como siempre, la propia documentación de
Unity.
También hay muchos tutoriales en el sitio web de Unity:
http://unity3d.com/support/documentation/
Además, el Unify Wiki es una fuente excelente de información contribuida por los usuarios:
http://www.unifycommunity.com
Y, por último, usted puede hablar con expertos y recién llegados en los foros de Unity:
http://forum.unity3d.com /
89
Apéndice de Scripts
Aquí se congregan todos los scripts
Script StartMenuGUI
Aquí está el código para el script StartMenuGUI.
//@script ExecuteInEditMode()
function OnGUI()
{
if(gSkin)
GUI.skin = gSkin;
else
Debug.Log("StartMenuGUI: GUI Skin object missing!");
GameOverGUI
Aquí está el código para el script GameOverGUI:
@script ExecuteInEditMode()
function OnGUI()
{
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2, Screen.height), "", background);
90
GameOverScript
Aquí está el código para el script GameOverScript:
function LateUpdate ()
{
if (!audio.isPlaying || Input.anyKeyDown)
Application.LoadLevel("StartMenu");
}
ThirdPersonStatus
Aquí está el código para el script ThirdPersonStatus:
// sound effects.
var struckSound: AudioClip;
var deathSound: AudioClip;
private var levelStateMachine : LevelStatus; // link to script that handles the level-complete sequence.
private var remainingItems : int; // total number to pick up on this level. Grabbed from LevelStatus.
function Awake()
{
levelStateMachine = FindObjectOfType(LevelStatus);
if (!levelStateMachine)
Debug.Log("No link to Level Status");
remainingItems = levelStateMachine.itemsNeeded;
}
health -= damage;
if (health <= 0)
{
SendMessage("Die");
}
}
91
function FoundItem (numFound: int)
{
remainingItems-= numFound;
if (remainingItems == 0)
{
levelStateMachine.UnlockLevelExit(); // ...and let our player out of the level.
}
}
function FalloutDeath ()
{
Die();
return;
}
function Die ()
{
// play the death sound if available.
if (deathSound)
{
AudioSource.PlayClipAtPoint(deathSound, transform.position);
}
lives--;
health = maxHealth;
if(lives < 0)
Application.LoadLevel("GameOver");
// If we've reached here, the player still has lives remaining, so respawn.
respawnPosition = Respawn.currentRespawn.transform.position;
// reset camera too
Camera.main.transform.position = respawnPosition - (transform.forward * 4) + Vector3.up;
// Hide the player briefly to give the death sound time to finish...
SendMessage("HidePlayer");
// Relocate the player. We need to do this or the camera will keep trying to focus on
// the (invisible) player where he's standing on top of the FalloutDeath box collider.
transform.position = respawnPosition + Vector3.up;
function LevelCompleted()
{
levelStateMachine.LevelCompleted();
}
92
LevelStatus
Aquí está el código para el script LevelStatus:
// This is where info like the number of items the player must collect
// in order to complete the level lives.
var itemsNeeded: int = 20; // This is how many fuel canisters the player must collect.
function UnlockLevelExit()
{
mainCamera.GetComponent(AudioListener).enabled = false;
unlockedCamera.active = true;
unlockedCamera.GetComponent(AudioListener).enabled = true;
exitGateway.GetComponent(AudioSource).Stop();
if (unlockedSound)
{
AudioSource.PlayClipAtPoint(unlockedSound, unlockedCamera.GetComponent(Transform).position, 2.0);
}
yield WaitForSeconds(1);
function LevelCompleted()
{
mainCamera.GetComponent(AudioListener).enabled = false;
levelCompletedCamera.active = true;
levelCompletedCamera.GetComponent(AudioListener).enabled = true;
playerLink.GetComponent(ThirdPersonController).SendMessage("HidePlayer");
playerLink.transform.position+=Vector3.up*500.0; // just move him 500 units
if (levelCompleteSound)
{
AudioSource.PlayClipAtPoint(levelCompleteSound, levelGoal.transform.position, 2.0);
}
levelGoal.animation.Play();
yield WaitForSeconds (levelGoal.animation.clip.length);
Application.LoadLevel("GameOver"); //...just show the Game Over sequence.
}
93
HandleSpaceshipCollision
Aquí está el código para el script HandleSpaceshipCollision:
94
In Unity, sound effects are implemented using Audio Source components, which handle various audio playback properties, such as pitch and volume. Sound effects like those on jump pads or pickup items require dragging the relevant sound clip into the script's defined audio property. It's important to adjust the pitch for variety when needed, especially for short effects like gunshots or footsteps. Consistency and realness in audio effects are maintained by correctly setting properties like Rolloff factor, which controls how sound diminishes over distance. Ensuring sound clipping issues are avoided in looping sounds is done by employing functions like 'Find zero crossings' .
Checkpoint systems like respawn points are crucial in platformer games for managing player progression and providing a base point for player revival after a character’s death. In Unity, respawn points help to offer a smooth gameplay experience, maintaining player engagement by reducing frustration from loss of progress. Typically, respawn points are managed as prefab instances, like RespawnPrefab, where each point can become active upon player interaction, determining the new spawn location upon the player's demise. This system provides logical checkpoints in gameplay, allowing for safe player reappearance .
In Unity games, scripting plays a critical role in managing audio effects for dynamic objects, such as jetpacks, enabling real-time control over audio playback based on game events. Unlike static audio sources, where the audio plays independently of in-game actions, dynamic audio allows for interactive sound effects that respond to player inputs or game states. For jetpacks, a looping sound effect is attached directly to the Player GameObject. The script controls starting and stopping this sound to match the physics of the jetpack's thrust, preventing audio clipping by ensuring the sound doesn’t restart unless stopped. This involves conditional checks and audio initialization in game start functions .
Using Physics components, such as colliders, is pivotal in Unity for managing realistic interactions between the player character and the environment. They enable the detection of collisions, providing crucial triggers for gameplay events. For example, the Box Collider in Unity can be used to detect when a player character falls out of the level or collides with environmental hazards. Implementing OnTriggerEnter() allows detecting when a GameObject, like a player, enters the collider's area, triggering appropriate responses such as invoking a FalloutDeath() function to handle the character's demise and subsequent respawn. This setup is integral to gameplay dynamics, handling interactions seamlessly and realistically .
Efficient management of object references in Unity is critical for performance optimization. Using functions like GameObject.Find() and getComponent() is slow and should be minimized, especially in performance-critical sections of the game. These functions are slow because they search the scene at runtime, introducing unnecessary computational work. Therefore, it's recommended to design systems that avoid frequent reevaluation of object states or dependencies. For dynamic scenarios, like determining which respawn point to use, it's essential to update references only when necessary rather than relying on these methods .
In Unity, prefabs are templates that can be reused across different projects or scenes, promoting reusability and efficiency. They allow developers to save a set of configured GameObjects, including their properties, components, and scripts, which can be instantiated multiple times. Transforming GameObjects into prefabs enables easy updates and management of similar objects. For instance, by creating a prefab of the Player object, all associated changes can be reused to instantiate new instances in different projects or scenes with consistent configurations, such as LerpzPrefab .
Caching enhances script performance in Unity by storing frequently accessed values, reducing the need for repetitive calls to functions like getComponent(), which can slow down the game. When managing state variables, caching allows a script to store the current state in memory, which is quickly accessible when needed, instead of recalculating or reloading these values from other scripts repeatedly. This is particularly useful in complex systems where scripts need frequent access to state-related variables maintained in different scripts, such as tracking player health or status .
The UnassignedReferenceException in Unity occurs when a script variable is not assigned any value. It is a common error for beginners in Unity. To resolve it, one must ensure that all required fields of scripts are correctly set. For instance, in the example provided, the NearCamera object needs its Target property assigned in the SpringFollowCamera script. This is achieved by dragging the Player GameObject from the Hierarchy panel to the Target field. The camera won't function unless this is addressed, and the Target must have an associated ThirdPersonController script, to allow the camera to follow the player's actions .
Unity scripts facilitate player control systems by implementing the logic behind player interactions, movements, and reactions in the game environment. A third-person controller script, for instance, closely links camera views with player movement, requiring dependencies like Character Controller components to manage physical interactions accurately. Additionally, such scripts may depend on animations and input management to modify a player's avatar according to commands. The dependencies often necessitate that supporting scripts and components, like SpringFollowCamera, are integrated to handle camera perspectives relative to player actions, ensuring smoother transitions and responsive gameplay .
The concept of 'Hot Changes' in Unity allows developers to modify game object properties and components during runtime, enabling real-time visualization of changes and immediate testing. This helps in fine-tuning and adjusting gameplay elements and settings on-the-fly without stopping the game. However, its primary limitation is that these changes are not permanent; they are discarded once the game is stopped. To retain changes made during play, developers must stop the game and manually apply the changes before running it again, preventing potential data loss and ensuring consistent configurations .