[PROTOTIPO][#1] Comienzo

ARQUITECTURA

Una arquitectura de software no es mas que unas reglas que seguir para desarrollar una aplicación. Siguiendo estas reglas se resuelven los problemas modernos que puede ocasionar tener un desarrollo largo sin reglas. ¿Os imagináis 😅?

También es necesario un motor de videojuegos, yo me decanto por Unity 3D. Es un motor con mucha comunidad, mucha documentación y con el que mas he desarrollado.

Ante todo decir que no soy ningún experto ni mucho menos me acerco. Puede ser que mi planteamiento sea lejano o incluso erróneo, pero de los errores se aprende. Al ser un juego con mucha cantidad de datos (Táctico) y no necesitar un intercambio frenético de información dinámica, de todos los patrones de diseño me decanto mas por el Modelo-vista-controlador (MVC).

Ya entro con un pie mal, ya que Unity 3D tiene una arquitectura Entidad-Componente (EC), pero eso no afectara a nuestro patrón siempre y cuando tengamos las referencias bien atadas.

Como pone en el titulo, esto es un prototipo para ver si es viable la idea de videojuego que tengo en mi cabeza. Nada es definitivo y seguramente en lo que tarde en terminar el proyecto se cambiaran muchas cosas.

De momento con cubos nos conformamos 💯

INICIO

Menu Principal

PERSISTENCIA

Me gustaría dejar zanjado el sistema de persistencia desde el principio, ya que es una parte muy importante para poder crear ciertos puntos de guardado en cada una de las versiones y poder probar de nuevo el mismo camino y comprobar si algo se a roto.

Unity tiene una sección donde explica su sistema de persistencia PlayerPrefs. Aunque empieza definiéndote su clase como un sistema de persistencia, termina diciéndote que no es una solución viable para producción. Por lo tanto decidí realizar una investigación de las formas mas comunes de guardar datos en disco. El resumen es que hay dos formas viables entre muchas otras: Serialización Binaria & Texto Plano.

Cada uno con sus ventajas y desventajas. La serialización binaria es mucho mas rápida pero puede causar el típico guardado corrupto. El texto plano es algo mas lento pero no se suele corromper y puede ser visto desde un editor de texto. Volvamos a este punto algo mas tarde.

La gestión de datos va a ser muy grande y mas en este tipo de juegos, por lo que lo voy a gestionar internamente con  Scriptable Objects, que son una nueva clase que ha implementado Unity para poder almacenar grandes cantidades de datos con un mínimo de memoria ocupada.

Esto son buenas noticias, ya que son fácilmente editables desde el inspector y no hay que ir creando archivos externos que luego ir cambiando como datos planos. ¿Cual es el problema entonces?, pues que solo guardan datos estáticos, en cierto modo, no es así, sino que son datos que se pueden modificar en tiempo de ejecución pero luego al cerrar el entorno (en este caso el juego), vuelven a su estado inicial.

Estado Inicial Estado En Ejecución Estado Final
int 0 int 2 int 2
bool true bool false bool true

Quitando este detalle, la nueva clase ScriptableObject es muy potente sabiendo sus limitaciones. La estructura que quiero montar seria un sistema central que tuviera en memoria una clase ScriptableObject llamada cartucho que contendrían los datos. Esta clase cargaría los datos externos y los asignaría a los valores del cartucho, desde aquí solo queda distribuir cada valor a su respectivo sistema.

La funcionalidad requerida es llegar a un punto en concreto y guardar. No es posible el autoguardado ni tampoco el guardado siempre que se quiera. Digamos que solo puedes guardar en unos puntos establecidos ya o teniendo un objeto en el inventario y estando en el mapa global. Se que es un sistema arcaico que solo se usaba en la ps1 o ni eso, pero es que la experiencia del usuario depende del camino que elijas para caminar, sin poder revertir esa elección.

Ciertamente es un sistema que no es muy viable para guardar cada cierto tiempo, ciertas variables, o para estar guardando y cargando constantemente. Pero hay que crear sistemas para la funcionalidad requerida, ni mas ni menos.

Con esto en mente, volvamos a la parte de elección entre formato de guardado exterior. Claramente los dos son buenos, pero en mi caso,  JSON es una opción mas que valida. Texto plano, se puede transferir entre dispositivos y no sufre ningún daño al modificarlo, es rápido, puede ser abierto con editor de texto…

Con esto planteado, el flujo seria:

  • Cuando se quiere cargar, se leen los datos del JSON externo.
  • Distribuir los datos leídos por los sistemas que corresponda.
  • Cuando se quiere guardar, se escriben los datos actuales en el cartucho.
  • Se vuelven a escribir en el archivo externo JSON.

Para comprobar que todo funcionara bien, cree una pequeña interfaz de opciones prototipada con el nuevo sistema de UI mejorado (en la version 4 era infumable) para modificar elementos esenciales como el sonido, las resoluciones, configuraciones gráficas…

Este es el archivo que es creado con formato JSON externo. Es bastante intuitivo y modificable incluso fuera del juego.

Imagen del JSON

TABLERO

El tablero es como he llamado a el campo donde se realizara el combate, es una parte complicada fácil sabiendo que los datos van por un lado y la lógica por otro. El primer acercamiento que propuse fue el de crear una matriz en memoria del tamaño que se quiere y crear por cada posición un objeto en el tablero, escalando en Y para conseguir altura, esto como puedes ver es algo caótico, resulta que para crear un nivel medio (20x20x20) se generan alrededor de 8000 objetos y eso solo para obtener posiciones del tablero.

Entonces vi que lo que necesitaba no era una estructura neandertal, tenia que seguir el con el patrón estipulado, (tarde poco en saltármelo 😄).

Separe los datos, por un lado, las posiciones las separe en una matriz de vector3 con xyz, por otro lado desde el inicio cargaba una lista con una matriz de posiciones para generar un campo vació y en vez de crear todos los objetos solo creaba uno por xz pero lo colocaba en la posición donde y fuera la mas alta. Esto me da que por anchura y profundidad es inevitablemente necesario crear todas las posiciones pero en y solo creo 1 posición siendo la mas elevada que es la que se usara.

Con esto se optimiza a 400 objetos.

Ahora quería ya probar como se sentía el recorrer el tablero, y solo hay que ver el genero para percatarse de que es muy importante tener un indicador/marcador de posicionamiento, para que el jugador tenga un enfoque rápido en caso de desorientación.

Esto es un enfoque primitivo al indicador final, como ya e dicho es fase de prototipo, por lo que cambiara al llegar la fase alfa/beta, pero me gustaría que el movimiento no sea brusco entre posición y posición. Esto lo digo porque la primera funcionalidad que he realizado se notaba muy tosca, simplemente el indicador cambiada de posición y la cámara realizaba un movimiento suavizado hacia el indicador.

Por lo que en vez de cambio brusco, he creado un objeto dentro del indicador para realizar un movimiento suavizado en relación al axis que se esta moviendo, haciendo que al mover el joystick en x 0.5+ la velocidad de movimiento es inferior a que si en x es 1.0f+.

Desplazamiento de Indicador

En futuras implementaciones incorporare un ajustes para poder cambiar la sensibilidad y que los jugadores puedan cambiar la velocidad de movimiento.

CONCLUSIONES

Resumen

Sorprendido de Unity 5, vengo de la version 4 que ha tenido muchos problemas de rendimiento y crasheos en medio de cargas de activos y pensaba que la version 5 estaría rota, pero no. Es igual de estable que mi querida Unity 3.3 y encima trae nuevas mejoras que se agradecen ya, como es el nuevo sistema de interfaz sin fallos (en la version 4 no se podía usar bien).

Se definió la arquitectura a la que se optaría (luego ya se vera si puedo seguir el proyecto sin desviarme 😄).

Se creo una escena inicial que mostrara el logo y algo de información dando tiempo para cargar los datos externos.

Investigué sobre las posibles opciones de persistencia en Unity y decidí quedarme con JSON, creando por el camino una UI para probar la persistencia con las opciones básicas.

Por ultimo se definió una pequeña clase para crear en memoria un tablero donde podernos mover libremente y empezar a construir sobre el un sistema de combate por turnos.

[PROTOTIPO][#2] Menú Principal
/img/ref.png
.