Logo Studenta

TFG_ENRIQUE_VAL_ASENSIO_2

¡Este material tiene más páginas!

Vista previa del material en texto

Universidad Politécnica
de Madrid
Escuela Técnica Superior de
Ingenieros Informáticos
Doble Grado en Ingeniería Informática y Administración y
Dirección de Empresas
Trabajo Fin de Doble Grado
Desarrollo de un Videojuego Educativo
para el Aprendizaje de Mecanografía
Autor: Enrique Val Asensio
Tutor(a): Antonio Jesús Díaz Honrubia
Madrid, Junio 2023
Este Trabajo Fin de Doble Grado se ha depositado en la ETSI Informáticos
de la Universidad Politécnica de Madrid para su defensa.
Trabajo Fin de Doble Grado
Doble Grado en Ingeniería Informática y Administración y Dirección de Em-
presas
Título: Desarrollo de un Videojuego Educativo para el Aprendizaje de
Mecanografía
Junio 2023
Autor: Enrique Val Asensio
Tutor: Antonio Jesús Díaz Honrubia
Lenguajes y Sistemas Informáticos e Ingeniería de Software
Escuela Técnica Superior de Ingenieros Informáticos
Universidad Politécnica de Madrid
Resumen
Actualmente, vivimos en una sociedad cada vez más informatizada. La mayoría
de puestos de trabajo, así como los estudios de distintos niveles, requiere el uso
de sistemas informáticos para su correcto desempeño. El problema radica en
que no todas las personas tienen los conocimientos adecuados para el manejo
de estos sistemas en materias tan básicas como es la mecanografía. Es por ello
que se ha ideado un proyecto de desarrollo de un videojuego cuyo objetivo prin-
cipal no es solo entretener a sus usuarios, sino también educarlos en la técnica
de la mecanografía. Esto se pretende conseguir de forma orgánica y natural,
pues, en vez de simplemente indicarle un texto o una serie de caracteres que de-
be introducir sin ningún incentivo, se le ofrece una experiencia lúdica en el que
se pone al usuario en situaciones de tensión en las que, inconscientemente, es-
cribirá de modo más rápido para sobrevivir a todos los obstáculos y enemigos en
la partida que esté jugando. Estos enemigos presentarán retos mecanográficos
únicos, divertidos y originales.
Para ello, se explicará en detalle las tecnologías que se han empleado para este
desarrollo, así como la metodología que se ha decidido seguir. Posteriormente,
se explicará la planificación del proyecto, explicando la organización, en cuanto
a materias de tiempo y esfuerzo, que se quiere seguir para poder desarrollar las
distintas tareas. Estas tareas se corresponderán con las numerosas funcionali-
dades que tiene el videojuego, las cuales son explicadas con gran detalle en el
apartado de «Desarrollo».
Luego, se realizarán ciertas pruebas de usabilidad realizada por usuarios de
todas las edades y niveles de mecanografía para comprobar si se cumple con
los objetivos principales del proyecto, realizando un análisis exhaustivo de los
resultados obtenidos, así como de las opiniones de los usuarios cuestionados.
Por último, se valorará el impacto que puede tener este proyecto a distintos
niveles, como puede ser el impacto social y económico. Además, se realizarán
ciertas conclusiones en contraste con los objetivos inicialmente marcados, así
como una conclusión personal y una lista de tareas correspondientes al trabajo
futuro.
i
Abstract
Currently, we live in an increasingly computerized society. Most jobs, as well
as studies at several levels, require the use of computer systems for a proper
performance. The problem is that not everyone has the appropriate knowledge
to handle these systems in basic areas such as typing. That’s why a project has
been devised to develop a videogame whose main goal is not just to entertain its
users, but also to educate them in the technique of typing. This is intended to be
achieved organically and naturally. Instead of simply indicating a text or a series
of characters that the user must type without any incentive, a fun experience is
offered where the user is put in tense situations in which, unconsciously, they
will type faster to survive all obstacles and enemies in the game they are playing.
These enemies will present unique, entertaining, and original typing challenges.
To this end, the technologies used for this development will be explained in
detail, as well as the methodology that has been chosen to follow. Subsequently,
a project planning will be explained, describing the organization, in terms of time
and effort, that is intended to follow in order to develop numerous tasks. These
tasks will correspond to several functionalities that the video game has, which
are explained in greater detail in the «Development» section.
Then, certain usability tests will be carried out by users of all ages and typing
levels to check if the main objectives of the project are met, performing a thor-
ough analysis of the results obtained, as well as the opinions of the surveyed
users. Finally, the impact that this project can have at different levels, such
as social and economic impact, will be evaluated. In addition, certain conclu-
sions will be made in contrast to the initially set objectives, as well as a personal
conclusion and a list of tasks corresponding to future work.
iii
Tabla de contenidos
1. Introducción 1
1.1. Motivación del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Contexto del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4. Estructura de la memoria . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Tecnologías empleadas 5
2.1. Motor gráfico: Unity . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2. Lenguaje de programación: C# . . . . . . . . . . . . . . . . . . . . . . 6
2.3. Sistema Gestor de Bases de Datos: SQLite . . . . . . . . . . . . . . . 6
2.4. Edición de audio: Audacity . . . . . . . . . . . . . . . . . . . . . . . . 7
2.5. Edición de animaciones: Piskel . . . . . . . . . . . . . . . . . . . . . 8
2.6. Control de versiones: Plastic SCM . . . . . . . . . . . . . . . . . . . . 8
2.7. Gestión de la metodología «Agile»: Jira . . . . . . . . . . . . . . . . . 9
3. Metodología 11
4. Planificación del proyecto 15
5. Desarrollo 17
5.1. Primeras configuraciones y lectura de movimiento del jugador . . . 17
5.1.1. Prefabs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.1.2. Componentes de un objeto . . . . . . . . . . . . . . . . . . . . 19
5.1.3. Consideraciones relevantes de programación en Unity . . . . 21
5.2. Implementación del movimiento del jugador . . . . . . . . . . . . . . 24
5.3. Implementación de acciones asociadas palabras . . . . . . . . . . . 26
5.3.1. Uso de las Coroutines . . . . . . . . . . . . . . . . . . . . . . . 28
5.4. Aparición de obstáculos de manera aleatoria . . . . . . . . . . . . . 30
5.5. Interfaz del usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.5.1. Canvas y elementos de la interfaz . . . . . . . . . . . . . . . . 31
5.5.2. Diccionario y objetos . . . . . . . . . . . . . . . . . . . . . . . . 33
5.5.3. Vidas del jugador . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.6. Implementación de los objetos . . . . . . . . . . . . . . . . . . . . . . 34
5.7. Implementación de enemigos comunes . . . . . . . . . . . . . . . . . 37
5.7.1. Enemigo Láser . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.7.2. Enemigo explosivo . . . . . . . . . . . . . . . . . . . . . . . . . 38
v
TABLA DE CONTENIDOS
5.7.3. Enemigo escudero . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.7.4. Enemigo stun . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.8. Jefes finales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.8.1. Jefe de Agujero Negro . . . . . . . . . . . . . . . . . . . . . . . 45
5.8.2. Jefe Ninja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.8.3. Jefe Duelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.8.4. Jefe Final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.9. Configuración de la Base de Datos . . . . . . . . . . . . . . . . . . . 57
5.10.Implementación de cooldowns . . .. . . . . . . . . . . . . . . . . . . 58
5.11.Spawn de palabras: Cofres . . . . . . . . . . . . . . . . . . . . . . . . 59
5.12.Sistema de control de daño . . . . . . . . . . . . . . . . . . . . . . . . 61
5.13.Spawn Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.14.Implementación de elementos de audio . . . . . . . . . . . . . . . . . 65
5.15.Implementación de menús . . . . . . . . . . . . . . . . . . . . . . . . 66
5.15.1.Niveles de dificultad . . . . . . . . . . . . . . . . . . . . . . . . 70
5.16.Implementación del tutorial inicial . . . . . . . . . . . . . . . . . . . 71
6. Evaluación de pruebas de usabilidad 75
7. Análisis de impacto 87
8. Conclusiones y trabajo futuro 89
Bibliografía 91
vi
Índice de figuras
2.1. Captura de la pestaña de Plastic SCM dentro del editor de Unity . 9
3.1. Tablero de Jira en el que se muestran las últimas «user stories» . . 12
3.2. Extracto de todos los changesets y ramas creadas en PlasticSCM . 13
4.1. Diagrama de Gantt que contiene la planificación del proyecto . . . 16
5.1. Herramienta Unity Hub . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.2. Esqueleto de una clase de instanciación de un prefab . . . . . . . . 21
5.3. Código de ejemplo para mostrar el acceso a los componentes de un
GameObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.4. Sprite del objeto que proporciona la palabra «laser» al jugador . . . 27
5.5. Esqueleto del código de una Coroutine que espera una determinada
cantidad de segundos . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.6. Escena del juego en el que aparecen dos asteroides en dos carriles
distintos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.7. Captura del medidor de velocidad de tecleo medida por palabras
por minuto (ppm) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.8. Representación en la interfaz de las vidas del jugador . . . . . . . . 34
5.9. Sprite del enemigo láser básico . . . . . . . . . . . . . . . . . . . . . . 37
5.10.Sprites de los distintos modelos de las variantes de enemigo láser . 38
5.11.Sprite que representa al enemigo explosivo . . . . . . . . . . . . . . . 39
5.12.Sprite que representa el prefab de enemigo escudero . . . . . . . . . 40
5.13.Cabecera de la función que encuentra al enemigo más cercano . . . 40
5.14.Captura de pantalla de los distintos tags a escoger en el proyecto . 41
5.15.Captura de pantalla en la que se ve cómo el enemigo escudero pro-
tege a un objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.16.Sprite que representa el prefab de enemigo stun . . . . . . . . . . . . 43
5.17.Primer frame del sprite animado del Jefe de Agujero Negro . . . . . 45
5.18.Imagen del primer frame del objeto animado del agujero negro . . . 46
5.19.Captura del combate contra el Jefe de Agujero Negro . . . . . . . . . 47
5.20.Primer frame del sprite animado del Jefe Ninja . . . . . . . . . . . . 48
5.21.Captura del combate contra el Jefe Ninja . . . . . . . . . . . . . . . 49
5.22.Primer frame del sprite animado del Jefe Duelo . . . . . . . . . . . . 49
5.23.Captura del combate contra el Jefe Duelo en la que el jugador ha
ganado una ronda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.24.Captura de la segunda fase del combate contra el Jefe Duelo . . . . 52
vii
Plastic
SCM
Unity
PlasticSCM
Unity
Hub
GameObject
ÍNDICE DE FIGURAS
5.25.Sprite del Jefe Final que se corresponde con uno de los frames que
representan su animación . . . . . . . . . . . . . . . . . . . . . . . . 53
5.26.Captura del ataque con múltiples láseres del Jefe Final . . . . . . . 53
5.27.Captura del ataque de ráfaga de misiles del Jefe Final . . . . . . . . 54
5.28.Captura del ataque de aturdimiento del Jefe Final . . . . . . . . . . 55
5.29.Captura del escudo del Jefe Final al estar a mitad de vida . . . . . . 55
5.30.Captura de las distintas palabras que un jugador ha recolectado en
su diccionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.31.Captura en la que aparece un cofre que contiene una de las «pala-
bras» que podrá usar el jugador . . . . . . . . . . . . . . . . . . . . . 60
5.32.Captura de la escena en la que el jugador puede ejecutar el coman-
do «abrir» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.33.Captura en la que se ha obtenido la palabra «tesla» al abrir el cofre 62
5.34.Captura del menú principal que el jugador verá al abrir el juego . . 67
5.35.Captura del menú con las distintas opciones de configuración . . . 68
5.36.Captura de la pantalla de pausa ejecutada en mitad de la partida . 69
5.37.Captura de la pantalla de derrota por haber perdido todas las vidas 69
5.38.Captura de la pantalla de victoria tras haber derrotado al Jefe Final 70
5.39.Captura de la pantalla que permite seleccionar una de las tres difi-
cultades del juego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.40.Captura del tutorial inicial del juego en el que se explica el movi-
miento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6.1. Primeras dos preguntas del cuestionario acerca de la información
de los usuarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.2. Tercera y cuarta pregunta del cuestionario . . . . . . . . . . . . . . 77
6.3. Preguntas del cuestionario relacionadas con la dificultad del juego 78
6.4. Preguntas del cuestionario relacionadas con el tecleo de comandos 79
6.5. Pregunta de respuesta larga sobre el peor elemento de la experiencia 80
6.6. Pregunta de respuesta larga sobre el mejor elemento de la experiencia 81
6.7. Pregunta de respuesta corta sobre el mejor boss del juego . . . . . 82
6.8. Preguntas de valoración numérica relacionadas con los objetivos
principales del juego . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.9. Gráfico sobre la pregunta acerca de si se ha experimentado algún
bug durante la experiencia . . . . . . . . . . . . . . . . . . . . . . . . 84
6.10.Pregunta de respuesta larga sobre la lista de errores que han sufrido 85
viii
Capítulo 1
Introducción
En este primer capítulo se explicará la motivación del proyecto, qué necesidades
satisface, en qué contexto se desarrolla, los objetivos que se persiguen durante
su elaboración y, finalmente, la estructura que presentará el resto del proyecto.
1.1. Motivación del proyecto
Actualmente es innegable la imperante relevancia de un manejo adecuado y
eficiente de las tecnologías de la información y comunicación. Las nuevas ge-
neraciones si destacan por algo es por su conocimiento y experiencia nativa de
móviles, tabletas y ordenadores.
En lo que se refiere a la eficiencia en el uso de las TIC, no solo podemos ha-
cer mención del hecho de saber utilizar de forma correcta un navegador web o
determinados programas. Entre estas habilidades eficientes también podemos
situar un manejo de la mecanografía apropiado, pues escribir, ya sean cortos o
extensos textos, con un teclado es de las actividades más básicas y repetidas
que hallamos en la informática.
Como se analizará en el contexto del proyecto, actualmente no se dispone de una
gran variedad de herramientas para el aprendizaje de la mecanografía, pues la
mayoría de las opciones que encontramos se basan en aplicaciones web que
permiten analizar la velocidad de tecleo. El aprendizaje en estas aplicaciones
surge de la voluntad de mejora de la última marca obtenida en lo que se refiere
a palabras por minuto.
Además, estas herramientas no resultan de por sí entretenidas para el usuario,
sino que la persona promedio su aprendizaje se basará en cursos externos de
escritura mediante teclado y un posterior análisis de su velocidad usando estas
herramientas.
Es por ello por lo que se ha decidido diseñar un producto interactivo que resulte
entretenido para cualquier persona, independientemente de la edad o experien-
cia con el manejo de teclados, y que le permita aprender mecanografía mientras
se divierte.
1Capítulo 1. Introducción
La manera de hacer este producto innovador es mediante un videojuego para or-
denador, en el que toda mecánica dependa de la escritura mediante teclado. De
este modo, se consigue atraer a usuarios de todas las edades y con distintos ob-
jetivos. Existirá un segmento que quiera aprender (para el cual existirá un nivel
de dificultad ajustable que sirva como entrenamiento), pero también tendremos
que contar con aquellas personas que busquen simplemente un entretenimiento
con el que, además, aprenderán esta habilidad.
1.2. Contexto del proyecto
La mecanografía no solo es algo básico en el conocimiento de las TIC, sino que
además en algunos países como en Finlandia está ocupando mucha más impor-
tancia el aprendizaje de la mecanografía que el de escribir a mano de manera
tradicional, incluso llegando a casi reemplazarla [1]. Esto es algo que tiene mu-
cho sentido en la sociedad en la que vivimos, pues en la gran mayoría de traba-
jos, facultades o incluso escuelas la mayoría de los textos que debemos escribir
no lo hacemos a mano, sino mediante el uso de un ordenador.
Del mismo modo que los escolares aprenden caligrafía en el colegio mediante el
uso de cuadernos dedicados a este tipo de aprendizaje, encontramos algo que
se puede asemejar a la mecanografía. La forma que más comúnmente emplean
los usuarios para adquirir velocidad en su escritura a máquina son aplicaciones
web, las cuales les muestra por pantalla una secuencia de palabras para medir
a qué velocidad escribe dicho usuario. La media de un usuario corriente es de
45-60 palabras por minuto, mientras que un profesional puede alcanzar las 150
palabras por minuto [2].
El problema está en que no existe una amplia gama de herramientas para el
aprendizaje de la mecanografía y, además, que los programas ya citados previa-
mente sirven principalmente para la medición de la velocidad que ya posee el
usuario, sirviendo esta propia métrica y el afán por mejorarla como incentivo a
conseguir una mejor técnica. Esto implica que los usuarios que sean novatos en
la mecanografía o simplemente quieran ejercicios que realmente les enseñen a
mejorar, se ven muy limitados en estos ámbitos.
Además, esto es una gran oportunidad para poder alcanzar un desarrollo más
sostenible a través del apoyo al ODS 4 (educación de calidad) y el ODS 8 (trabajo
decente y crecimiento económico). Como se estudiará posteriormente, unos 750
millones de adultos en todo el mundo seguían siendo analfabetos en 2016, sien-
do dos tercios de este número mujeres. Aunque la tasa de alfabetización no es
igual en todas las regiones, se puede apreciar que todavía queda mucho camino
por recorrer para poder obtener unos resultados deseables.
1.3. Objetivos
El objetivo general es el desarrollo de un videojuego para el aprendizaje de meca-
nografía usando Unity, ofreciendo distintos desafíos que pongan a prueba tanto
la velocidad como la precisión del tecleo por parte de los usuarios.
2
Unity
1.4. Estructura de la memoria
Para conseguir este objetivo, podemos descomponerlo en diversos objetivos es-
pecíficos:
1. Investigación exhaustiva de los distintos métodos de desarrollo de videojue-
gos y aprendizaje de las herramientas, motor gráfico y lenguajes a emplear.
2. Definición de las distintas funcionalidades que debería incorporar el video-
juego en función a lo que se pretende incluir como mecánicas jugables, así
como establecer un sistema de control de versiones.
3. Desarrollo e implementación de las distintas funcionalidades previamente
descritas para obtener un videojuego de buena calidad.
4. Implementación de niveles de dificultad adaptativos en función al nivel de
mecanografía que puedan tener los distintos usuarios a los que queremos
dirigirnos.
5. Elaboración de pruebas unitarias y de integración para comprobar cada
funcionalidad desarrollada, así como la puesta en marcha de distintas
pruebas de usabilidad con usuarios de todos los niveles de técnica de me-
canografía.
6. Evaluación de los resultados de las pruebas de usabilidad para el análisis
de apartados a mejorar y para la comprobación del cumplimiento de la
premisa de mejora del nivel de mecanografía.
1.4. Estructura de la memoria
Los próximos capítulos de la presente memoria seguirán la siguiente estructura:
En el capítulo 2, podremos encontrar las distintas secciones que corresponderán
con cada una de las tecnologías empleadas en el desarrollo de este videojuego,
explicando por qué se han escogido las susodichas en vez de otras tecnologías
de características similares.
En el capítulo 3 se valorará la metodología que seguirá el desarrollo software.
Dentro del capítulo 4 se explorará la planificación de las distintas tareas que se
ha elaborado para una correcta organización del tiempo y del esfuerzo para el
proyecto expuesto en este documento.
El desarrollo del producto software se detallaré en profundidad en el capítulo 5,
estructurando este capítulo en función del cometido que tienen los numerosos
scripts según su funcionalidad para el juego. Además, se explicarán las cues-
tiones que se consideren más relevantes para que el lector pueda comprender
los aspectos de Unity más útiles que se han empleado para implementar las
funcionalidades que se describan.
En el capítulo 6 se analizarán los resultados de las pruebas de usabilidad, dividi-
das según el segmento de usuarios en los que podamos seccionar los potenciales
clientes según su nivel de mecanografía para poder explorar las tres dificultades
3
Unity
Capítulo 1. Introducción
con las que cuenta en juego. En la industria de los videojuegos, esto es lo que
se denomina la fase de game testing.
En el capítulo 7 se evaluará el impacto social y cualitativo que ha tenido el
desarrollo de este trabajo.
En el capítulo 8 se realizarán ciertas conclusiones en función a los objetivos
planteados al comienzo del trabajo y se determinará si se han cumplido los
mismos.
Finalmente, encontraremos la Bibliografía, que contará con todas las referencias
que se citarán en el trabajo y un Anexo.
4
Capítulo 2
Tecnologías empleadas
En este capítulo se expondrán las distintas tecnologías empleadas en el desarro-
llo de este videojuego, explicando por qué se han escogido estas en vez de otras
tecnologías de características similares.
2.1. Motor gráfico: Unity
El motor gráfico es la base de cualquier videojuego. Es el encargado de propor-
cionar los gráficos, de ensamblar los scripts programados por los desarrolladores
y definir sus comportamientos relacionándolos a los distintos objetos del juego,
de establecer las reglas para simular la física interna y de generación de luces y
sombras.
Unity es uno de los motores de uso gratuito más famosos en el sector de desa-
rrollos de videojuegos. Las empresas más grandes poseen sus propios motores
desarrollados e integrados internamente por expertos en software, lo cual re-
quiere unas aportaciones dinerarias de millones de euros. Es por eso que es
muy común que las empresas más pequeñas de desarrollo de videojuegos (las
llamadas coloquialmente empresas indie) emplean motores gráficos de uso gra-
tuito.
Unity tiene un competidor muy potente en este mercado, y que suele ser la
alternativa para este tipo de empresas a la hora de seleccionar un motor: Unreal
Engine.
La elección que se ha hecho para este trabajo ha sido basada en el acceso a
distintos cursos profesionales de plataformas externas. Previo al comienzo del
desarrollo de este trabajo, se han realizado distintos cursos de aprendizaje de
Unity y de las tecnologías derivadas para familiarizarse con el entorno gráfico.
Además, Unreal Engine suele estar asociado a proyectos de mayor calibre con
gráficos de última generación, mientras que Unity es un motor que se suele
usar para proyectos más humildes como pueden ser juegos 2D o aplicaciones
móviles [3].
5
Unity
Unity
Unity
Unity
Capítulo 2. Tecnologías empleadas
2.2. Lenguaje de programación: C#
C# es el lenguaje de programación que emplea Unity para la creación de los
scripts que determinaránlos distintos comportamientos que se puedan apreciar
en el producto final.
La programación de un videojuego en Unity sigue un modelo de programación
orientada a objetos, pues crearemos clases que se asociarán a los distintos obje-
tos o elementos del juego (por ejemplo, clase Player.cs) y podremos crear estos
objetos en el resto de las clases accediendo a sus atributos (siempre que sean
visibles para la clase desde la que se llama a estos) de una manera similar a la
que se programa en otros lenguajes orientados a objetos, como puede ser Java.
Todos estos objetos que crearemos deben derivar de una clase, que incorpo-
ran las librerías de Unity, denominada MonoBehaviour. Esta clase incorporará
todos los métodos necesarios para poder funcionar en Unity, como puede ser
alguno de los más comunes el método Start, que es llamado en el primer frame
en el que aparece el objeto con el script atribuido; el método Update, llamado
cada frame (por lo que si el juego se reproduce a 60 frames por segundo, será
llamado 60 veces cada segundo), o el método OnTriggerEnter2D, el cual nos per-
mite realizar comunicaciones entre scripts cuando dos objetos colisionen en la
escena del juego [4].
La elección de este lenguaje ha venido determinada por haber seleccionado
Unity como motor gráfico del videojuego, ya que, como se ha comentado pre-
viamente, es el lenguaje que utiliza por defecto. Si se hubiera escogido Unreal
Engine en vez de Unity, se hubiera escogido programar en otros lenguajes. En
este caso, el lenguaje sería C++ y Blueprint Visual Scripting[4].
2.3. Sistema Gestor de Bases de Datos: SQLite
Este videojuego emplea también una base de datos embebida que se utiliza para
almacenar el progreso del jugador, sus preferencias de configuraciones y tam-
bién para almacenar tablas que contendrán palabras y textos que se consultarán
para extraer un texto aleatorio para distintas mecánicas del juego.
Esta última funcionalidad también se podría haber implementado mediante un
archivo simple de texto que contuviera una palabra o un texto por cada línea, y
el script que lo tuviera que llamar leyera el archivo y seleccionara una palabra
o texto de forma aleatoria. Se ha decidido emplear la implementación basada en
la base de datos en busca de mejorar el rendimiento del juego.
Se ha escogido el SGBDR SQLite antes que otros sistemas gestores de SQL más
populares, como MySQL o MariaDB, por diversas razones [5]:
1. La primera razón es porque sus transacciones no requieren ningún servidor
ni configuraciones para poder ejecutarse.
6
C#
Unity
Unity
Player
cs
Unity
Mono
Behaviour
Unity
Unity
Unity
C++
Blueprint
Visual
Scripting
2.4. Edición de audio: Audacity
2. Al tratarse realmente de una biblioteca de C de código abierto que imple-
menta un SGBD, el tamaño que ocupa es mucho menor que el resto de las
opciones.
Este aspecto cobra mucha importancia en un videojuego, debido a que
son productos software que ocupan normalmente mucho espacio, por lo
que una cuestión crítica es la reducción del tamaño y la búsqueda del
rendimiento.
3. Atendiendo a esta búsqueda del mayor rendimiento, también podemos be-
neficiarnos de las consultas eficientes y rápidas que ofrece SQLite.
Además de todas estas razones, existe un plug-in en la tienda comunitaria de
Unity (Unity Asset Store) que facilita las conexiones de una base de datos de
SQLite llamada «SimpleSQL» [6]. Este plug-in incorpora una clase en la bibliote-
ca del juego llamada «SimpleSQLManager», la cual implementa diversos métodos
que permiten realizar transacciones de manera sencilla. La conexión con la ba-
se de datos queda realmente simplificada también, pues solo tendremos que
arrastrar el archivo que contiene la misma en una sección que nos creará este
plug-in.
2.4. Edición de audio: Audacity
Toda acción, elemento o animación cuenta con una pista de audio única. Ade-
más del elemento sonoro más importante: la música. La mayoría de las pistas
de audio han sido extraídas de plataformas online que sirven como repositorios
gratuitos de sonidos. Algunos de los que se han usado para este proyecto han
sido Zapsplat [7], Soundbible [8] o Freesound [9]. Otros sonidos y, principal-
mente, la música de fondo ha sido extraída de la ya mencionada Unity Asset
Store.
La cuestión reside en que muchas de estas pistas de audio deben ser tratadas
previamente a su inclusión en el proyecto. Un ejemplo de esto sería la música
que sonaría de fondo, pues esta debe tener una introducción que solo sonaría
una única vez, pero debe estar seguida de una pista que suene naturalmente
como su continuación, pero que sea un bucle, pues no podemos estimar cuánto
tiempo va a estar el usuario jugando.
Es por ello por lo que una de las mayores labores que se han llevado a cabo en
cuanto a edición de audio se refiere ha sido hacer esta división entre introduc-
ción y la parte que se repite (también llamada loop), así como la propia creación
de un bucle que sonara natural y que el usuario no notara la vuelta al inicio de
la pista. Un proceso similar se ha tenido que ejecutar con sonidos de acciones o
de elementos, pues algunos debían también ser un sonido cíclico.
Para realizar todo este procedimiento de edición de audio se ha usado el pro-
grama Audacity, software de uso gratuito que tiene su origen en el año 2000.
Este programa permite al usuario la grabación, edición y exportación de audio
de gran calidad de forma sencilla.
7
Unity
Unity
Asset
Store
Zapsplat
Soundbible
Freesound
Unity
Asset
Store
Audacity
Capítulo 2. Tecnologías empleadas
Se ha elegido este software frente a otros competidores, como pueden ser, por
ejemplo, AdobeAudition o AVSAudioEditor, por su fácil accesibilidad y fami-
liaridad debido a que es un programa que suele ser estudiado en materias de
la Educación Secuandaria como Tecnologías de la Información y Comunicación.
Además, Audacity, como ya se ha comentado antes, es de uso gratuito, mien-
tras que los dos programas competidores mencionados son herramientas profe-
sionales que exigen una compra de licencia para su uso.
2.5. Edición de animaciones: Piskel
Al igual que algunas pistas de audio, muchos sprites han sido obtenidos de la
Unity Asset Store, algunos de ellos siendo gratuitos y una gran mayoría con
un determinado coste.
Por otro lado, la mayoría de las animaciones de distintos elementos que compo-
nen el juego han sido animados desde cero. Esto ha supuesto un determinado
aprendizaje sobre la creación de imágenes y de animaciones siguiendo el estilo
pixel art.
Para ello, se ha usado el software gratuito de creación de sprites y animaciones
especializado en el estilo que se buscaba (el ya mencionado pixel art) denomi-
nado Piskel. Este programa ofrece diversas herramientas, al igual que com-
petidores como pueden ser Adobe Photoshop o Aseprite, para la edición de
imágenes.
La primera diferencia, nuevamente, es el precio, debido a que estos dos compe-
tidores requieren la compra de una licencia de uso. Por otro lado, Piskel ofrece
una versión muy simplificada de la creación de animaciones mediante una he-
rramienta que permite la edición de imágenes por fotogramas. El usuario irá
creando sprites, uno por cada fotograma, y en la esquina superior derecha se irá
mostrando como quedaría la animación resultante.
2.6. Control de versiones: Plastic SCM
El proyecto se ha trabajado en local por ciclos, como se comentará en el apartado
3. Cada vez que se cumplía el objetivo del ciclo, se subía a una plataforma en la
nube para mantener los cambios. Esto se asemejaría en gran medida al llamado
GitFlow, el cual determina el procedimiento que llevaría el desarrollo software y
su gestión de versiones y ramas mediante el uso de Git+GitHub.
La mayor diferencia es que en vez de usar este control de versiones tan am-
pliamente extendido, se ha decidido usar otro tipo de software. Durante todo el
proyecto, se ha usado Plastic SCM.
La razón de ello se debe a que es un software muy similar a GitHub, pero es
propiedad de Unity, por lo que es algo que se puede encontrar integradoen
la propia plataforma del editor de Unity. Esto es, al realizar los cambios que
cumplan de manera satisfactoria lo que se buscaba en el ciclo, solo habrá que
8
Adobe Audition
AVS Audio Editor
Audacity
Unity
Asset
Store
Piskel
Adobe
Photoshop
Aseprite
Piskel
Git+GitHub
Plastic
SCM
GitHub
Unity
Unity
2.7. Gestión de la metodología «Agile»: Jira
darle a un botón, en una pestaña del propio editor llamada «Plastic SCM», que
dice lo siguiente: «Checkin changes».
Con esta acción, automáticamente se guardará un «changeset» en la rama en la
que se esté trabajando, como se puede apreciar en la Figura 2.1.
Figura 2.1: Captura de la pestaña de Plastic SCM dentro del editor de Unity
Como se ve en la imagen, se seleccionarán los archivos cuyos cambios se deseen
subir a la nube. Se comentará esto en mayor profundidad en el apartado 3.
2.7. Gestión de la metodología «Agile»: Jira
Al igual que se ha comentado en el apartado 2.6, esta sección se expondrá en
profundidad en el capítulo 3.
Jira es un software online de gestión de un proyecto «agile». En él se crean
las llamadas «user stories», las cuales son divisiones de los ciclos que se han
comentado anteriormente. Estas corresponden con los requisitos software de
manera atomizada. Además, también permite la generación de un calendario de
cumplimiento de estas «user stories» en el llamado «planning».
Existen diversos competidores ampliamente usados, como puede ser Rally. Su
cometido y funcionalidad es muy similar, pero la ventaja que ha determinado el
uso de Jira frente a Rally es que la primera dispone de una aplicación móvil
que permite su uso de forma muy accesible en cualquier momento.
Aparte de esto, ofrece de manera muy sencilla la organización de las tareas y los
equipos encargados de ellas.
9
Plastic
SCM
Unity
Jira
Rally
Jira
Rally
Capítulo 3
Metodología
Como se ha anticipado en el apartado 2.7, se ha optado por una metodología
«Agile» para el desarrollo de este proyecto. Esto se debe a la facilidad de atomizar
los requisitos software que debe incorporar el videojuego. Se ha adaptado este
tipo de metodología para un equipo con un solo desarrollador. Esto implica que
en la gestión de esta metodología no se le ha dado importancia a la distribución
de tareas entre miembros del equipo, sino que lo primordial ha sido establecer
las correspondientes tareas y asignarles una fecha límite de implementación.
El procedimiento que se ha seguido ha sido el siguiente:
1. Determinar nuevas «user stories», categorizarlas (como se explicará más
adelante) y asignarles una fecha límite en función a los requisitos software.
2. Creación de nuevas ramas para funcionalidades que pudieran alterar la
funcionalidad base de la aplicación.
3. Desarrollo de las nuevas funcionalidades.
4. Elaboración de pruebas exhaustivas.
5. Marcar el desarrollo de las «user stories» en Jira.
6. Cuando se obtiene un resultado satisfactorio, se realizará un «merge» desde
la rama creada (si procede) a la rama principal (denominada «main»). Esto
implica que la funcionalidad desarrollada es algo definitivo y se traslada a
la base del juego.
7. Cada dos semanas, se generaba un ejecutable provisional del juego en for-
ma de DEMO para su comprobación de la funcionalidad y satisfacción de
los resultados del ciclo.
8. Repetir el proceso de forma recursiva.
En la Figura 3.1 se puede apreciar cómo es el «Tablero» que muestra Jira para
resumir las «user stories» que quedan por hacer, las que están en curso y las
completadas. Debido a que esta última categoría de tareas completadas se vacía
cada cierto tiempo, se pueden ver en la imagen solo 2 tareas completadas.
11
Jira
Jira
Capítulo 3. Metodología
El número de cada «user story» es indicativo de la existencia de al menos 68
tareas anteriores.
Figura 3.1: Tablero de Jira en el que se muestran las últimas «user stories»
Con la generación de nuevas «user stories», procede una correcta categorización
para una posterior creación de ramas en Plastic SCM. Distinguimos cuatro
tipos distintos de tareas:
Feature: Referido a tareas que suponen la implementación de nuevos ele-
mentos en el proyecto. Es la categoría más recurrida por su naturaleza a la
hora de categorizar nuevas implementaciones.
Animation: Con Feature nos referimos a nuevas implementaciones en cuan-
to a software se refiere. La gran mayoría de elementos software, en el con-
texto del desarrollo de un videojuego, deben contener un componente visual
en forma de animación. Es por ello por lo que muchas tareas categorizadas
como Feature se corresponden posteriormente con otra tarea independiente
categorizada como Animation.
Bugfix: Tareas nacidas de las pruebas o «testeos» de nuevas implementa-
ciones en los ciclos ya mencionados. Si se encuentra un error o comporta-
miento no deseado (más conocido como «bug»), se genera una nueva tarea
con esta categoría que queda pendiente de ser arreglada.
Config: Referido a las tareas de configuración externa de nuevos elementos
o plug-ins. Ejemplo de ello sería la conexión con la base de datos SQLite,
o la agregación del corpus (sobre el cual se hablará en profundidad en el
capítulo 5.
12
Plastic
SCM
SQLite
En cada rama encontramos los ya mencionados changesets, que son atomiza-
ciones de cambios realizados en la rama correspondiente. En la Figura 3.2 se
puede observar una pequeña sección de todo el flujo de las ramas usadas en
el desarrollo de este proyecto, pues se han producido tantos changesets que es
imposible mostrar todas las ramas instanciadas.
Figura 3.2: Extracto de todos los changesets y ramas creadas en PlasticSCM
En la imagen se pueden ver distintos «puntos», que representan los changesets.
Cada punto cuenta con un mensaje escrito por el desarrollador que debe indicar
el cambio que se ha realizado en ese momento. También se pueden observar
las derivaciones de unas ramas a otras y luego sus convergencias en diversos
puntos.
Esto se debe a que, por ejemplo, al implementar una funcionalidad resulta nece-
sario introducir un mecanismo descrito por otra «user story» antes de terminar
la primera.
Una vez ya realizadas una serie de pruebas para comprobar su correcto fun-
cionamiento, se hará «merge» con la rama padre, es decir, incorporar todos los
cambios de forma definitiva en la rama que se estaba trabajando previamente.
13
PlasticSCM
Capítulo 4
Planificación del proyecto
Primeramente, antes de la elaboración de cualquier producto software, y en es-
pecial a los que llevan tanto tiempo de desarrollo y esfuerzo como son los video-
juegos, cabe realizar una planificación del proyecto que se va a realizar.
Se han definido distintas tareas que comprenderán diversos grupos de funcio-
nalidades. Estas son:
Implementación de bases mecánicas: Comprende distintos aspectos que
servirán como base del juego para el usuario. Incluye las acciones que
puede usar el jugador, la interfaz, los obstáculos básicos y los gestores
de aparición de los distintos elementos del juego, también llamado Spawn
Manager.
Implementación de enemigos comunes: Estos son los enemigos que apa-
recerán de forma concurrente a lo largo del juego. Cada uno poseerá un
comportamiento único y diferente al resto. Son cuatro: el enemigo láser, el
explosivo, el escudero y el enemigo stun.
Implementación de jefes finales: Son los mayores retos mecanográficos
que pondrán a prueba el nivel de tecleo del usuario, tanto en aspectos
de su velocidad como en su precisión. Cada uno ofrecerá una experiencia
original y diferenciada entre ellos. Estos son cuatro también: el Jefe del
Agujero Negro, el Jefe Ninja, el Jefe Duelo y el Jefe Final.
Se puede observar en la Figura 4.1 la planificación basada en estas agrupacio-
nes de las funcionalidades las distintas tareas principales y más notorias del
desarrollo del videojuego.
15
Capítulo 4. Planificación del proyecto
Figura 4.1: Diagrama de Gantt que contiene la planificación del proyecto
16
Capítulo 5
Desarrollo
Como se ha visto en el apartado 3, se han desarrollado muchas implementacio-
nes de diversostipos distribuidas en distintas «user stories». Es por ello por lo
que el desarrollo de la aplicación se va a estructurar según las funcionalidades
que cumplan estas «user stories».
Se escogerán las tareas más relevantes de cada ciclo y se irá explicando su fun-
cionamiento para poder obtener al final una visión con la mayor profundidad
posible para poder entender los elementos por lo que está compuesto este video-
juego educativo.
Para mantener la cohesión en la redacción de este documento, se explicarán
las tareas por orden de implementación. Pero al incluir una «user story» que
pertenezca a un tipo de funcionalidad del producto que se asemeje a otras tareas
posteriormente realizadas, se explicarán estas también en el mismo apartado
(ignorando en este caso el orden cronológico) en aras de mantener una correcta
organización.
Debido a que esta es una memoria sobre un trabajo de desarrollo software, se
omitirán las «user stories» de categoría Animation. De forma análoga tampoco
se incluirán, a no ser que sea necesaria su explicación, las tareas de Bugfix,
pues resultan ser de poca relevancia para dar un contexto del funcionamiento
del producto final.
5.1. Primeras configuraciones y lectura de movimiento
del jugador
Los tres primeros cambios («changesets») realizados correspondían a dos tareas
iniciales. Una de ellas era la configuración inicial del proyecto.
Esto implicaba la creación del proyecto mediante la herramienta llamada Unity
Hub, la cual es una aplicación de gestión de todos los proyectos de Unity. En
esta herramienta se selecciona el tipo de videojuego que se desea crear (ya sea
2D, 3D, o siguiendo una plantilla por determinado), como se puede apreciar en
la Figura 5.1.
17
Unity
Hub
Unity
Capítulo 5. Desarrollo
Figura 5.1: Herramienta Unity Hub
Una vez creado el proyecto, se importaron los Assets que se estimaron necesa-
rios para el comienzo del proyecto. Entre estos Assets se pueden destacar los
materiales del background o del fondo. También se incluyeron algunos sprites
iniciales, muchos de los cuales sirvieron como placeholders para implementar
las funcionalidades correspondientes a ellas para que, cuando el proyecto ya
hubiera avanzado lo suficiente, se cambiarán estos placeholders por sprites fi-
nales.
Además de esto, también se estableció la conexión con el servicio de Plastic
SCM. Para ello, se tuvo que crear una cuenta en dicho servicio y enlazarla con
el proyecto recién creado. Dentro de Unity, hubo que instalar un plug-in que
permitiera las opciones de control de versiones de este servicio.
Además de este plug-in, también se instalaron otros que resultaban esencia-
les para el desarrollo del videojuego, como puede ser el paquete denominado
TextMeshPro, el cual incorpora en un proyecto Unity opciones avanzadas de
incorporación y edición avanzada mediante código de textos y otros elementos
de UI, como pueden ser botones, dropdowns o sliders.
Una vez realizada la configuración inicial del proyecto, se procedió a los primeros
scripts. El primero que se creó fue el llamado Player, el cual controla todas las
acciones del jugador y se puede considerar la clase principal del videojuego, pues
cuenta con la mayor densidad de código de entre todos los scripts.
Antes de entrar en mayor profundidad en lo que se incluyó en este primer chan-
geset, hay que explicar ciertas funcionalidades sumamente importantes que in-
cluye Unity: los «prefabs» y los «componentes».
5.1.1. Prefabs
Como ya se ha comentado, el lenguaje de programación que utiliza Unity es C#,
y el paradigma de programación que se sigue es la Programación orientada a
18
Unity
Hub
Plastic
SCM
Unity
TextMeshPro
Unity
Unity
Unity
C#
5.1. Primeras configuraciones y lectura de movimiento del jugador
objetos (POO). Se creará, por lo general, una clase distinta para cada elemento
del juego que se considerará un objeto.
Cabe remarcar la diferencia entre objeto de programación (asociado a una clase
o script) y un objeto del editor (para el cual no es necesario que le corresponda
un script). Un ejemplo con el que esta distinción queda evidenciada sería la
cámara principal («Main Camera»), la cual es creada automáticamente con la
configuración inicial del proyecto, y mediante ella el jugador podrá observar la
escena en curso. Esta cámara es un objeto del editor Unity, la cual no tiene
ningún tipo de programación detrás por parte del desarrollador.
En el editor de Unity, cuando se quiere implementar un nuevo elemento, se
crea un nuevo objeto a partir de un sprite arrastrando este a la escena. A partir
de ese momento, este elemento ha sido creado como una especie de objeto que
tiene unos determinados atributos o comportamientos que determinemos para
ello. El problema es que, con este procedimiento, el objeto ha sido creado como
un elemento único (de una sola instancia) que existe en esa escena hasta que se
destruya.
Por ejemplo, si pensamos en un enemigo común (los cuales serán desarrollados
más adelante en esta memoria), al ser creado con su sprite y su comportamiento,
al derrotarlo desaparecerá (según hayamos determinado en su respectivo script)
y no podremos volver a utilizarlo, pues ya no existe en la escena. Es por ello por
lo que Unity incorpora una funcionalidad básica para poder instanciar todas
las veces que necesitemos un determinado objeto. Esto es lo que llamamos un
prefab[10].
Para crear un prefab, simplemente arrastraremos desde el editor el objeto que
hemos creado en la escena a una carpeta del proyecto que debemos crear lla-
mada «Prefabs». A partir de ese momento, el motor gráfico reconocerá el objeto
de manera distinta. A partir de ese momento, cuando traigamos un prefab a
escena, podremos hacer cambios en este y Unity nos preguntará si queremos
aplicar estos cambios a todas las instancias posteriores (lo que se denomina
«Override»).
5.1.2. Componentes de un objeto
Una vez tenemos un objeto (ya fuera de tipo prefab o no) en la escena, pode-
mos determinar los comportamientos o propiedades que puede tener añadiendo
los ya mencionados componentes. Existe una cantidad abrumadora de compo-
nentes en el motor de Unity[11]. Algunos ejemplos de ellos para ilustrar esta
funcionalidad básica son:
Transform: Es la propiedad más básica que puede tener un objeto. Incluso
cuando creamos un objeto vacío (Empty Object), siempre se le asigna este
componente por defecto. Indica la posición en los ejes X, Y, Z (siempre en
este orden). Además, también indica la rotación que presenta el objeto.
Sprite Renderer: Permite poder visualizar el sprite que se le haya asociado,
así como cambiar determinadas configuraciones. Ejemplos de estas son el
19
Unity
Unity
Unity
Unity
Unity
Capítulo 5. Desarrollo
color, la transparencia (denominada «alfa»), el material... Cuando se crea
un objeto directamente a partir de un sprite, como se ha descrito antes,
este componente se configura automáticamente.
Script: Cuando se ha programado el comportamiento que se quiera para
un determinado objeto, por ejemplo, el jugador, se le deberá asignar un
componente «Script» para que pueda ejecutar lo que se ha puesto por códi-
go.
RigidBody: Es el componente básico con el que el motor gráfico ejecuta
las físicas que incorpora. Es necesario agregarlo a cada elemento que que-
ramos que tenga cualquier comportamiento físico básico. Se referenciará
muchas veces para poder ejecutar acciones elementales mediante código,
como el movimiento del jugador o de los enemigos. Tiene propiedades físi-
cas como la masa, el multiplicador de gravedad, la aceleración...
Collider: Permite una de las formas más básicas y usadas de comunica-
ción entre distintos scripts. Por ejemplo, cuando un asteroide (el cual se
explicará más adelante), el cual se mueve en línea recta hacia abajo, im-
pacte con el jugador, gracias al componente Collider podemos coordinar
los dos objetos implicados en la colisión (como puede ser dañar al jugador
o destruir el asteroide).
AudioSource: Permite que un objeto sea una fuente de audio. A través de
él, se podrá hacer que suenenelementos de la clase AudioClip incorpora-
dos por MonoBehavour. Este AudioSource puede ser escuchado por otros
objetos que contengan el componente AudioListener, el cual suele estar
incluido en la ya citada Main Camera.
Animator: Como se comentó en el apartado 3, la gran mayoría de objetos
o elementos en Unity suelen ir acompañados por una animación corres-
pondiente para darle un cierto nivel de calidad al producto. Todas las «user
stories» de este proyecto han derivado en un tipo de archivo denominado
«animaciones» (*.anim). Estos archivos se han guardado en una carpeta del
proyecto llamada «Animations». Todas estas animaciones han sido asigna-
das a un objeto mediante el uso de este componente.
Al crear una nueva animación, se generan dos tipos de archivos:
1. Animation: Contiene los fotogramas que componen la animación. Acce-
diendo a ello, se puede cambiar la propia animación modificando cada
fotograma, cambiar la velocidad de reproducción o estableciendo si es
una animación en bucle o no.
2. Animator Controller: Controla el flujo de estados en una animación,
como si se tratara de un autómata de estados finitos. Se pueden esta-
blecer reglas para tratar mediante código el cambio entre «Animations».
Por ejemplo, si se quiere añadir una animación en bucle que indique al
jugador que está dañado, habrá que tener una animación para cuando
está en estado default (también llamado idle) y, mediante el uso de una
20
Collider
AudioClip
MonoBehavour
AudioSource
AudioListener
Unity
5.1. Primeras configuraciones y lectura de movimiento del jugador
using Unity.Engine;
public class EjemploInstantiate: MonoBehavour {
[SerializeField]
private GameObject _player;
...
public void InstantiatePlayer(){
Instantiate(_player, new Vector3(0,0,0),
Quaternion.identity);
}
void Start(){
InstantiatePlayer();
}
void Update(){
InstantiatePlayer();
}
}
Figura 5.2: Esqueleto de una clase de instanciación de un prefab
variable booleana, cambiar a la animación nueva cambiando el valor a
true.
LineRenderer: Otro componente que se ha usado en varias ocasiones en
este proyecto ha sido el llamado LineRenderer. Este es capaz de crear
una línea recta mediante código que una dos puntos que se indiquen en
el script correspondiente. Ejemplo claro de ello es el comportamiento del
enemigo stun, del cual se hablará en el apartado 5.7.4, pues este lanzará al
jugador un «gancho» que, en caso de colisionar con el jugador, le obligará a
escribir una determinada palabra extraída de una base de datos.
5.1.3. Consideraciones relevantes de programación en Unity
Estos prefabs se pueden instanciar mediante código usando una función que
incorpora MonoBehavour: Instantiate. A continuación se muestra un ejemplo
simplificado de programación de una clase que llama a un prefab del jugador.
Se expondrán ciertas consideraciones muy relevantes para este tipo de progra-
mación.
Con el código anterior se puede apreciar distintos aspectos de la programación
de videojuegos mediante Unity en C#:
Toda clase debe incorporar la librería Unity.Engine para poder imple-
mentar la clase padre MonoBehavour. Si se crea el script dentro del propio
editor, esta librería y la correspondiente herencia de la clase padre se in-
corporarán de forma automática.
21
true
LineRenderer
MonoBehavour
Instantiate
Unity
C#
Unity.Engine
MonoBehavour
Capítulo 5. Desarrollo
Siguiendo el paradigma de POO, la clase EjemploInstantiate tiene un
atributo denominado «_player», el cual es de tipo GameObject. Esta es una
clase objeto básica de MonoBehavour. Hace referencia a cualquier tipo de
objeto en Unity de forma genérica. Por ejemplo, al declarar el atributo como
este tipo de dato, se puede acceder a los métodos de la clase, como puede
ser SetActive(boolean), el cual permite activar o desactivar el objeto
mediante código.
Es importante recalcar que, sabiendo que _player contendrá un objeto pre-
fab que representará al Player (con su script homónimo correspondiente),
no podemos acceder a los métodos públicos de este citado script, pues per-
tenecen al tipo de dato Player, y no GameObject. Para poder acceder al
script de Player, se deberá hacer lo siguiente:
Player player = _player.GetComponent<Player>();
Se seguirá de forma análoga este procedimiento para cualquier tipo de com-
ponente de un objeto. Por ejemplo, para obtener el componente LineRender
de un enemigo stun, se ejecutará lo que se puede ver en la Figura 5.1.3.
[SerializeField]
private GameObject _stunEnemy;
...
LineRenderer lineRenderer=
_stunEnemy.GetComponent<LineRenderer>();
Figura 5.3: Código de ejemplo para mostrar el acceso a los componentes de un
GameObject
Una convención que se ha decidido adoptar en el desarrollo de todo el
código de este proyecto es que las variables que sean declaradas como
private deberán empezar por el carácter «_». De este modo se podrá saber
con facilidad su estado de visibilidad con respecto a otras clases mientras
se está desarrollando el software. Es por esto por lo que se han creado
variables como _player o _stunEnemy.
Una línea que ha aparecido en los códigos de ejemplo hasta ahora y no se ha
explicado su funcionalidad es [SerializeField]. Bien es sabido el uso de
las declaraciones public/private de los atributos de una clase en POO.
Esta declaración de visibilidad de los atributos tiene algunas implicaciones
más en la programación orientada a Unity.
En el Inspector del editor es donde podemos observar y editar todas los
propiedades y componentes de un determinado objeto. En el componente
de «Script» aparecerán los atributos públicos, pero no los privados. Que
un atributo aparezca en el editor nos permite asignarle un valor mediante
el editor (sin uso del código), simplemente arrastrando el elemento que
queramos o escribiendo su valor en caso de ser un tipo básico de dato.
22
POO
EjemploInstantiate
GameObject
MonoBehavour
Unity
SetActive(boolean)
Player
Player
GameObject
Player
Player
player
_player.GetComponent<Player>();
LineRender
GameObject
[SerializeField]
public/private
Unity
5.1. Primeras configuraciones y lectura de movimiento del jugador
Pero existen ocasiones en las que queremos asignar un determinado ele-
mento al valor de un atributo que necesitamos que sea privado mediante
el editor debido a que no podemos acceder al susodicho por código. Es pa-
ra esto mismo para lo que sirve la declaración [SerializeField] antes de
un atributo de clase. El dato seguirá siendo privado para el resto de scripts,
pero podremos verlo en el editor para su monitorización o asignación de un
valor.
Para el ejemplo en el que declarábamos el GameObject de un atributo lla-
mado _player, simplemente tendríamos que arrastrar el prefab correspon-
diente a Player hasta el campo que se muestra en el componente script.
La función Instantiate recibe tres parámetros:
1. El GameObject a instanciar. Normalmente se trata de un prefab.
2. La posición en la que aparecerá el objeto. Este parámetro suele ser con
un nueva posición (expresada como un nuevo objeto de tipo Vector3
(int x, int y, int z) o un elemento transform. Este último es un
atributo público de todo objeto GameObject, y hace referencia a su
componente «Transform».
Este elemento es una clase en sí, y tiene como uno de sus atributos
otra clase denominada «Position», la que devuelve la posición (que sería
un tipo de dato Vector3) en la escena del GameObject al que está aso-
ciado. Es por ello por lo que en este segundo parámetro podríamos es-
cribir object.transform.position en vez de crear otro Vector3 nue-
vo.
3. El último parámetro que recibe la función es la rotación del objeto.
Si queremos que no rote, entonces pondremos la rotación por defec-
to (Quaternion.identity). Si quisiéramos una determinada rotación
(por ejemplo, que un láser que dispare el enemigo rote 90 grados, de-
bido a que el sprite asociado esté en horizontal cuando queremos que
este se desplace hacia abajo), escribiríamos Quaternion.Euler(0,0,
90).
Lo que hará esta función será crear un clon del prefab que se le pasó como
primer objeto en laposición y con la rotación indicada.
Start y Update son dos funciones que se implementan de forma automáti-
ca (solo las cabeceras de las funciones, sin nada en el cuerpo) al crear una
clase que derive de MonoBehavour. Es por ello por lo que resulta relevante
una breve descripción de cada una.
Start es la función que se ejecuta en el primer frame en el que aparece el
objeto que contenga el script. Normalmente usado para inicializar variables
o para determinar comportamientos por defecto en un inicio. Por ejemplo,
si quieremos que el jugador aparezca en la posición (0,-4,0), en Start
deberemos escribir transform.position= new Vector3(0,-4,0).
23
[SerializeField]
GameObject
_player
Player
Instantiate
GameObject
Vector3
(int
x,
int
y,
int
z)
GameObject
Vector3
GameObject
object
transform
position
Vector3
Quaternion
identity
Quaternion
Euler
(0,0,90)
(0,0,90)
Start
Update
MonoBehavour
Start
(0,-4,0)
Start
transform.position=
new
Vector3(0,-4,0)
Capítulo 5. Desarrollo
Update es una función de absoluta importancia en este tipo de progra-
mación. Determina el comportamiento que debe tener un objeto de forma
continua, ya que se ejecuta cada frame. Esto es, si un juego está ejecután-
dose a 60 fps, implicará que la función Update será llamada 60 veces cada
segundo.
Esta función obliga a cambiar en cierto modo la forma clásica de pensar
para incorporar algoritmos a como estamos acostumbrados en otros len-
guajes de programación como Java o C. Por ejemplo, el código anterior
sería catastrófico para nuestro juego, pues lo que haría sería que instan-
ciaría una copia del prefab del jugador, no solo en el primer frame (por el
método Start), sino porque crearía 60 copias cada segundo.
5.2. Implementación del movimiento del jugador
Una vez explicados los conceptos necesarios en los anteriores apartados, pode-
mos entrar en mayor profundidad en lo desarrollado acerca de la primera «user
story» de tipo Feature: el movimiento del jugador.
Cabe remarcar que, al ser un juego educativo que pretende enseñar mecanogra-
fía, el movimiento del usuario no es uno que sea libre y mediante cuatro teclas,
como suele ser el caso en la amplia mayoría de videojuegos. En esta ocasión, el
usuario debe moverse escribiendo la dirección en la que se quiere desplazar.
Por ejemplo, el jugador siempre empieza el juego en la posición 0,-4,0. Por
lo que, si se quiere desplazar hacia la izquierda, deberá escribir por teclado la
palabra izquierda y presionar la tecla «Enter». Si lo ha escrito correctamente, la
nave que representa al jugador debe desplazarse a la izquierda hasta llegar a la
posición (-5,-4,0. Si intenta volver a escribir «izquierda», sonará un indicador
de error, pues entonces se saldría de la pantalla.
Esto se debe a que la pantalla se puede decir que se estructura en tres carriles:
Carril izquierdo: Posición (-5,y,0)
Carril central: Posición (0,y,0)
Carril derecho: Posición (5,y,0)
El código de este nuevo comportamiento del jugador se compone de diversas
partes que se incluyen en la clase Player.cs. Lo que se desarrolló en esta pri-
mera implementación se ha mantenido hasta el producto final. Se compone de
diversas partes que se incluyen en la clase Player.cs:
1. Por un lado, se ha decidido poner como atributo de clase una lista que
contiene diversos datos de tipo «string». Cada dato de esta lista se refiere
a una acción ejecutable por el usuario. Es por ello por lo que esta lista se
denomina diccionario.
Lo primero que ha sido incorporado en el diccionario para esta primera
implementación del movimiento han sido las siguientes palabras:
24
Update
Update
Java
C
Start
0,-4,0
izquierda
(-5,-4,0
(-5,y,0)
(0,y,0)
(5,y,0)
Player.cs
Player.cs
5.2. Implementación del movimiento del jugador
Izquierda
Derecha
Arriba
Abajo
2. Otro atributo que se ha incluido es el llamado «action», el cual es un «string»
que va recopilando lo escrito por el usuario.
Para ello, se hace uso de Input.inputString dentro del método Update
de la clase Player. Esto es algo que incorpora MonoBehavour, y permite
guardar en un «string» la tecla que haya presionado el usuario.
Sabiendo esto, lo que se ha hecho es que cada frame se analiza si ha escri-
to algo el usuario (Input.inputString!=""), y, en caso afirmativo, se le
suma a lo que ya tenía almacenada la variable «action».
Es entonces cuando se espera que el usuario presiona la tecla «Enter» pa-
ra ejecutar la acción escrita. De esto último es de lo que se encarga una
función fundamental en el código de Player: ReadAction. Esta función,
debido a su importancia desde estos primeros changesets hasta los últimos
creados, merece una descripción en más detalle de su funcionamiento:
Lo primero que se procesa es una transformación del campo action
para ponerlo en letras minúsculas (para que dé igual cómo escriba el
usuario) y se quitan los espacios en blanco innecesarios (usando la
función Trim().
Posteriormente a esta transformación, se compara con todos los ele-
mentos del diccionario del usuario mediante un bucle exhaustivo.
Si encuentra una entrada del diccionario que se corresponda con la
acción, entonces se procesa mediante un switch y se determina cuál
es el comando a ejecutar. Aquí es donde encontramos las redirecciones
correspondientes a todos los métodos de la clase Player que contienen
los distintos comportamientos o acciones del jugador.
Si no encuentra la acción escrita por el usuario en el listado dicciona-
rio, entonces comprobará si se encuentra en otro atributo denominado
objetos, también de tipo List<string>. Esto se explicará en profun-
didad en el apartado 5.6.
En caso de no cumplirse ninguna de las anteriores condiciones, enton-
ces simplemente se reproducirá, haciendo uso de la referencia corres-
pondiente al componente AudioSource de Player, un sonido de error
para notificar al usuario de su fallo al escribir.
3. Una vez se reconozca mediante la función recién descrita una dirección
en la que el jugador se desee mover, se realizará un mismo procedimien-
to para cualquier dirección (solo cambiarán los valores numéricos de las
posiciones).
25
Input.inputString
Update
Player
MonoBehavour
Input.inputString!=""
Player
ReadAction
Trim()
switch
Player
List<string>
AudioSource
Player
Capítulo 5. Desarrollo
Este procedimiento consiste en, primeramente, comprobar si se puede eje-
cutar la acción en función de la posición del jugador, pues no podemos
permitir el movimiento si este supondría la salida de la escena. Es por ello
por lo que se comprueba que el eje X o Y no exceda un número en concreto.
En caso de que se permita ejecutar la acción, entonces simplemente se
procederá a dar un valor adecuado a otro atributo de Player, denominado
«target». Este parámetro es de tipo Vector3, y es usado en el método Update
en una función MoveTowards. Esta función recibe por parámetro un vector
al que desplazarse a una determinada velocidad.
La velocidad que hay que usar en la función es determinada por otro atri-
buto de la clase: _speed. Sabemos, gracias a su nomenclatura, que es de
tipo private. Es importante la mención de este parámetro, pues será men-
cionado en otras funcionalidades de la clase Player, pero también será un
campo que todo objeto susceptible a un movimiento deberá poseer.
5.3. Implementación de acciones asociadas palabras
El siguiente requisito software que se implementó tras desarrollar el movimiento
del jugador y, consecuentemente, el reconocimiento de comandos escritos por el
usuario, fue la implementación de la primera palabra o acción: láser.
Para ello, se creó un nuevo objeto de tipo prefab con un nuevo script correspon-
diente. Lo único que se programó en un primer momento en esta clase Laser
recién creada fue un movimiento vertical a una determinada velocidad (paráme-
tro _speed). Como este comportamiento se quiere incluir desde el primer frame
en el que se instancie un clon del láser, se incorporó este código en el método
Start.
Posteriormente, se le añadió un componente Collider al nuevo prefab para que
se pueda detectar cuando impactecontra los futuros enemigos u obstáculos.
Finalmente, para terminar la implementación de esta funcionalidad, solo queda-
ba reconocer la palabra cuando la escribiera el usuario. Es por ello que se agregó
un nuevo caso en el ya mencionado switch de ReadAction. Este ejecutaba una
nueva función Laser(), la cual simplemente instanciaba una copia de un nuevo
atributo de tipo GameObject llamado «_laserPrefab».
Pero para reconocer esta palabra, como se ha visto en el apartado 5.2, debe
estar incluida la palabra «laser» en el diccionario. Para hacer esto, se creó otro
objeto prefab llamado «Laser_palabra». Este objeto presenta una animación que
será similar para el resto de palabras. El primer frame de esta animación se ve
representado por la Figura 5.4.
Este nuevo elemento tenía un sprite y animación correspondiente, ambos crea-
dos correspondiéndose a unas determinadas «user stories» de tipo Animation.
Se han eliminado los acentos de las palabras de acción por motivos de la fuen-
te que se usa para representar estas palabras, por lo que en este documento
las palabras que se mencionen no se les incluirá acento para remarcar que se
26
Player
Vector3
MoveTowards
Player
Laser
Start
Collider
switch
ReadAction
Laser()
GameObject
Animation
5.3. Implementación de acciones asociadas palabras
Figura 5.4: Sprite del objeto que proporciona la palabra «laser» al jugador
trata de un comando, como por ejemplo «laser» o «cañon». Las tildes se pueden
practicar en otros apartados, como las palabras de aturdimiento (ver apartado
5.7.4).
También contaba con un componente Collider y con un nuevo script: Palabra.
En este se tiene un atributo de clase llamado «wordID», el cual se le da valor
mediante el editor. Luego, se analiza mediante un switch(wordID) cuál es el
elemento que ha recolectado (colisionando con él) el jugador. Dependiendo del
elemento del que se tratara, se añade un string u otro en el diccionario del
jugador.
Tras cierto tiempo y debido a razones de diseño, se decidió finalmente incor-
porar la palabra «laser» en el diccionario inicial del jugador, por lo que ya no
serviría en principio el objeto «Laser_palabra» para su uso. Sin embargo, sí ser-
viría como modelo de diseño para el resto de palabras que posteriormente se
implementarían:
Misil: Un proyectil con mayor daño y tamaño, lo que implica un mayor área
(llamada comúnmente hitbox) de activación otrigger del Collider. Produce
también al impactar un tipo de prefab denominado «explosion_misil», el
cual también tiene un Collider para poder impactar a enemigos cercanos.
Cañón: Un ataque que atraviesa toda el eje vertical y atraviesa dañando
todo lo que esté por en su rango.
Tesla: Una acción no dirigida al daño, sino a la estrategia, pues, duran-
te sus cinco segundos de duración, todo lo que entre en contacto con su
Collider será paralizado.
Pulso: Una secuencia de tres proyectiles de gran velocidad, pero poco daño.
Escudo: Activa un objeto hijo de Player, mediante el uso de la ya men-
cionada función SetActive de la clase GameObject, que sirve como pro-
tección del daño contra el jugador. Esto es algo que se desarrollará en el
apartado 5.12.
27
Collider
Palabra
switch(wordID)
Collider
Collider
Collider
Player
SetActive
GameObject
Capítulo 5. Desarrollo
Curación: Simplemente sirve para curar al jugador. Al igual que el ante-
rior elemento Escudo, también se explicará en mayor profundidad en el
apartado 5.12.
Varias de estas palabras se agruparon en una categoría internamente tratada
de manera similar. Son los llamados Proyectiles, y son las palabras Laser, Misil
y Pulso . Se ha creado una nueva clase llamada Proyectil de la que, median-
te herencia de clases, derivan las otras respectivas clases. El motivo de esta
agrupación será desarrollado en el apartado 5.6
Algunos de estas acciones a las que llama son simples usos de la función
Instantiate, como es el caso de Laser() o Missile(). Sin embargo, otras acciones
hacen uso de una funcionalidad clave en el desarrollo de videojuegos mediante
Unity que necesita ser desarrollada, pues es utilizada en la gran mayoría de
clases del proyecto. Se trata de las «Coroutines».
5.3.1. Uso de las Coroutines
Las Coroutines o corrutinas son una funcionalidad clave para la programación
de distintas funcionalidades en Unity. Permiten ejecutar en segundo plano las
acciones que se le indiquen.
Ofrecen características de concurrencia que pueden ayudar a mejorar conside-
rablemente el flujo de ejecución del código. Sin embargo, como suele ocurrir con
accesos concurrentes a determinados datos compartidos, se debe proceder con
cuidado al usar estas funcionalidades.
Además, hay que tener también en cuenta que en este tipo de programación tan
singular los objetos asociados a los distintos scripts pueden desaparecer en cual-
quier momento mediante el uso de la función Destroy de la clase GameObject.
Esto quiere decir que, si tenemos por ejemplo un enemigo_laser (explicado en el
apartado 5.7.1) y este llama a una corrutina, puede ocurrir que el jugador ataque
al enemigo y este se vea obligado a destruirse. Esto provocará que la corrutina
llamada por la clase Enemigo_laser se vea abortada de forma repentina.
Una característica también que resulta relevante en la materia de las corrutinas
es que no son funciones void, sino que deben retornar siempre un tipo de dato
IEnumerator. Esto implica que la función debe contener una línea de yield
return. Los datos IEnumerator que se devuelven en las corrutinas están rela-
cionados con distintos tipos de funciones que obligan al programa a esperar en
el background.
La que más se ha usado en el desarrollo de este proyecto es la función WaitFor-
Seconds(float seconds), que, como indica su nombre, espera una determinada
cantidad de segundos que se le pasen por parámetro, y será entonces cuando
continúe el flujo del código del resto de la corrutina.
En la Figura 5.3.1 se puede apreciar cómo es el esqueleto más usual de una
corrutina y su funcionamiento.
28
Proyectil
Instantiate
Unity
Unity
Destroy
GameObject
Enemigo_laser
void
IEnumerator
yield
return
IEnumerator
5.3. Implementación de acciones asociadas palabras
using Unity.Engine;
public class EjemploCoroutine: MonoBehavour {
public int test;
void Start(){
test = 0;
StartCoroutine(Test());
}
void Update(){
Debug.Log(test);
}
IEnumerator Test(){
test = 1;
yield return new WaitForSeconds(5.5f);
test = 2;
}
}
Figura 5.5: Esqueleto del código de una Coroutine que espera una determinada
cantidad de segundos
Lo que se muestra en esta clase EjemploCoroutine tiene el siguiente funciona-
miento:
Se ha declarado un atributo test que va a ser mostrado por pantalla 60
veces por segundo al estar en el método Update.
Al instanciarse el objeto que contenga este script, es decir, cuando se llame
al método Start, se le dará un valor inicial a test de 0. Además, se llamará
a la corrutina declarada en la misma clase denominada Test.
Al igual que la llamada a toda corrutina se realiza con el método Start-
Coroutine, se puede suspender en cualquier momento su funcionamiento
con StopCoroutine, o incluso detener todas las corrutinas de la clase con
StopAllCoroutines.
Lo que hace esta corrutina es asignar el valor de test a 1. Entonces, tras
5.5 segundos de espera, cambiará el valor de este campo a 2.
Sabiendo estos datos, podemos conocer el resultado de lo que se imprime
por pantalla gracias al uso de Debug.Log. Podemos suponer que se im-
primará 60x5.5=330 veces el número 1 y después, una vez transcurridos
cinco segundos y medio, solo se mostrará el número 2.
29
EjemploCoroutine
Update
Start
test
0
Test
test
1
5.5
2
Debug.Log
60x5.5=330
2
Capítulo 5. Desarrollo
5.4. Aparición de obstáculos de manera aleatoria
El objetivo que se planteó con el diseño del videojuego desde su concepción fue
crear una herramienta de aprendizaje de la mecanografía de una manera poco
convencional a lo que podemos encontrar hoy en día. La idea de mejora de esta
técnica vendría de poner al usuario en situaciones de tensión en el que se veaobligado a escribir cada vez más rápido debido a un incremento constante de la
dificultad.
Esta dificultad se refiere realmente a la aparición de distintos enemigos y obs-
táculos. Los enemigos serán tratados más adelante en el apartado 5.7. Sin em-
bargo, una vez implementados los controles básicos del jugador, llegó el mo-
mento de desarrollar situaciones que obligaran al usuario a moverse, es decir,
a tener que escribir las palabras correspondientes al movimiento o a diversos
ataques para poder sobrevivir.
Estas situaciones serían primeramente creadas gracias a los obstáculos ya men-
cionados. Estos obstáculos son asteroides que irán apareciendo cada determi-
nado tiempo (como se tratará en el apartado 5.13).
Como se quiere conseguir forzar al usuario a realizar movimientos de forma
continua, se decidió generar estos prefabs de los asteroides por pares. Se generó
una corrutina que, cada determinado tiempo, generara de forma aleatoria un
asteroide que ocupara uno de los tres carriles de la pantalla. Una vez sabido
cuál es este carril ya ocupado, se crea seguidamente un segundo prefab del
asteroide en otro carril distinto de forma aleatoria.
En la imagen que se muestra en la Figura 5.6 se puede apreciar cómo sería una
situación real de la escena cuando aparecen dos asteroides de forma aleatoria.
En este caso en el carril izquierdo y central, por lo que el jugador debería escribir
«derecha» para poder esquivar estos obstáculos.
Figura 5.6: Escena del juego en el que aparecen dos asteroides en dos carriles
distintos
30
5.5. Interfaz del usuario
5.5. Interfaz del usuario
Lo siguiente que se realizó fue un primer boceto de lo que más tarde sería la
interfaz final del usuario o UI (User Interface). Es por ello por lo que, en aras
de la claridad, se va a proceder a desarrollar todos los elementos gráficos que
forman esta interfaz.
Antes de presentar cualquier elemento de UI, se necesita explicar el concepto de
Canvas.
5.5.1. Canvas y elementos de la interfaz
Unity incorpora diversas herramientas de interfaz. Entre estas podemos encon-
trar:
Texto: Nos permitirá escribir lo que deseemos en la pantalla, ya sea desde
el editor o desde código. Es algo que se utilizará en gran medida a lo largo
de este proyecto.
Panel: Definirá un elemento gráfico rectangular normalmente usado como
fondo (y como elemento padre) de otros elementos de UI, como puede ser
el texto. Por decisión de diseño, en este videojuego se ha decidido usar un
panel en la gran mayoría de casos en los que se ha incorporado un elemento
de texto.
Image: Permite la incorporación de sprites como parte de la UI. Se puede
acceder a un componente homónimo mediante código para poder tener un
elemento visual que vaya cambiando en función a un determinado com-
portamiento.
Botón: Son herramientas ya configuradas por Unity para poder hacer click
sobre ellas. El desarrollador deberá especificar los comportamientos deriva-
dos de accionar estos botones. Para ello, se deberá referenciar un elemento
cualquiera y usar una función de sus respectivas clases.
Por ejemplo, estos botones son utilizados en el menú principal para ofrecer
diferentes opciones al usuario. Si queremos generar un botón .Opcionesçon
el que se despliegue un menú de configuración, debemos entonces referen-
ciar el panel que contenga estas opciones y llamar a su función SetActive
(true) para que se muestre, a la vez que el panel de Main Menu se debe
ocultar usando SetActive (false) para evitar el despliegue de dos menús
de forma simultánea.
Slider: Son una herramienta también desplegada por Unity que permite,
desde su creación, poder arrastrar una barra lateral. Tienen un funciona-
miento similar a la barras de desplazamiento verticales y horizontales de
las páginas web para poder navegar a través de ellas.
Este elemento de UI ha sido empleado en el proyecto para definir una op-
ción de ajuste del volumen general del juego.
31
UI
Unity
Unity
SetActive
(true)
SetActive
(false)
Unity
Capítulo 5. Desarrollo
Cabe recalcar que Unity adquirió en 2017 un paquete creado por la comunidad
(antes solo disponible en la Unity Asset Store) de elementos UI denominado
TextMeshPro, el cual es realmente una mejora directa de estos elementos UI,
pues presentan una mejora visual, son más fáciles de configurar y de acceder
por código. Es por ello por lo que en este proyecto se han usado elementos UI
derivados de este paquete.
Expuestos los elementos que suelen componer cualquier interfaz, debemos co-
nocer el concepto de Canvas. Este es un GameObject generado automáticamente
cuando queremos incorporar nuestro primer elemento de UI, pues es obligatorio
que todo elemento de interfaz sea hijo de este objeto. Este GameObject tiene un
componente también llamado Canvas que permite la impresión o pintado de los
distintos elementos descritos por pantalla.
Se debe establecer un orden de pintado [12], el cual es determinado por el orden
jerárquico que sea establecido en el editor. También se mostrarán tres modo de
renderizado de los elementos de UI:
Espacio de la pantalla - Superposición (Overlay): Establece los elementos
de UI de forma superpuesta encima de la propia pantalla. Lo más impor-
tante que se debe remarcar de este modo de renderización es que, en caso
de cambiarse el tamaño de la pantalla, también se modificará el tamaño
del Canvas.
Espacio de la Pantalla - Cámara: Funciona de manera similar al anterior
pero, en vez de que su funcionamiento dependa de la propia pantalla, se
establecerá una dependencia con la cámara que se esté usando.
World Space: Este modo de renderización hace que los elementos hijos
pertenezcan al propio mundo, es decir, a la escena. Esto es útil si se de-
sea incorporar la UI en 3D como parte del juego más que como elementos
gráficos 2D.
Conocido todo el entorno de User Interface que proporciona Unity, podemos
describir los elementos de la interfaz con los que cuenta este proyecto.
Primeramente se diseñó un elemento que se estimó de necesidad superlativa pa-
ra una herramienta de mecanografía: un panel que mostrara el input del usua-
rio. Este traducía la ya mencionada variable action (consultar apartado 5.2) en
un entorno gráfico, para que el jugador conozca en todo momento lo que está
escribiendo.
Además, justo debajo existe un elemento de texto que muestra la velocidad de
tecleo medida en palabras por minuto (PPM). Esto se le muestra en pantalla con
un contador de las palabras que escribe por minuto, como se puede ver en la
Figura 5.7.
Esta velocidad de tecleo se calcula haciendo la media aritmética de lo que el
usuario ha tardado en escribir cada una de las palabras y objetos, es decir,
cualquier comando válido, a lo largo de toda la partida. Este es un gran incentivo
para que el jugador pueda mejorar su velocidad.
32
Unity
Unity
Asset
Store
GameObject
GameObject
Unity
5.5. Interfaz del usuario
Figura 5.7: Captura del medidor de velocidad de tecleo medida por palabras por
minuto (ppm)
El ya mencionado panel en el que se muestra lo que el jugador va escribiendo es
simplemente un panel UI que tiene un hijo de tipo TextMeshPro Text. Este texto
se inicializa como vacío y, mediante código, se irá editando en función a lo que
contenga la variable action descrita en el apartado 5.2.
El script Player se comunicará con otro script denominado UIManager, el cual
se encargará de todos los elementos gráficos que se incluyan. Este nuevo script
tiene una función ShowInput (stringinput) que modificará el texto del panel.
Esta función es llamada en el Update de Player, la cual recibirá por parámetro
la variable action.
5.5.2. Diccionario y objetos
El diccionario, explicado en el apartado 5.3, sabemos que es una lista de datos
de tipo string. Lo mismo ocurre con los objetos, los cuales todavía no se han
tratado en esta memoria.
Se consideró un requisito software necesario poder ofrecer al usuario qué pa-
labras o comandos puede ejecutar de forma visual por pantalla. Para ello, se
crearon dos paneles situados abajo en la pantalla, uno a la derecha (diccionario)

Continuar navegando

Materiales relacionados

466 pag.
Programación en "C"

Escola Jardim De Deus

User badge image

ALEXANDER MANUEL

315 pag.
Flash Guía de inicio

Continental

User badge image

Manuel Velázquez