Archivo del Autor: JC Reyes Ramos

Acerca de JC Reyes Ramos

Ing. Informático entusiasta de los videojuegos desde 1985. Cuando no juego a videojuegos, los creo.

Update #3 UnityCity (18/06/14)

Añadido control de cámara y un último retoque visual: nubes.

El color del atardecer/amanecer es provisional, a la espera de refinarlo un poco.

unitycity_daynnite_clouds

El control de horas y días esta terminado, así como el control de cámara. Puedes moverte por el mapa, rotarlo libremente 360º y modificar el zoom en hasta 7 niveles.

2-Sided Shader para Unity

Una de las principales carencias a la hora de importar objetos .FBX  desde 3D Studio Max, Maya, Blender, etc… a Unity, es la ausencia de un material por defecto 2-Sided.

Este material es necesario para evitar el siguiente “glitch” gráfico:

1-side falda 1-side

Ocurre el mismo efecto que con un plano. Es decir: si creamos un objeto “Plane” y le asignamos un material cualquiera (Diffuse por defecto), observamos que es visible únicamente por uno de los lados.

Para que este plano, y por lo tanto, cualquier objeto .fbx tenga material visible por ambos lados, sin necesidad de modelar un polígono cerrado por completo (como son el caso de melenas, faldas, telas, etc…), necesitamos un material que haga visible a estos planos por ambos lados.

Para ello podemos programar un shader propio.

Click derecho -> Create -> Shader.

Doble click y comenzamos a programar el shader (no confundir con “Open compiled shader”, ya que éste código es el generado por Unity tras compilar el shader).

El siguiente código muestra las propiedades para crear un shader de tipo diffuse y double-sided:

La propiedad más importante para conseguir esto es “Cull Off“. Con esto estamos desactivando una propiedad que sirve para optimizar el rendimiento a la hora de renderizar texturas y propiedades gráficas Direct3D.

Backface Culling” es una técnica de optimización que por defecto está activada para que no se rendericen las caras de los polígonos que el visor (o jugador) no este visualizando en ese momento. Por tanto, no es recomendable desactivar esta propiedad en todos los materiales, puesto que incrementaría de forma desmesurada los requisitos necesarios.

El siguiente código ShaderLab crea un material de tipo “Bumped Specular” y double-sided:

Y es el que uso para solucionar el glitch gráfico del anterior ejemplo, el cual queda así:

2-sided falda 2-side zapato.gif

Nótese que tanto la falda, como la tela roja de delante, como el interior de las botas ahora sí tienen textura, por lo que el resultado final es mucho más satisfactorio.

Modelo sobre el que aplico los shaders cedido por cortesía de Miguel Ángel López Amodeo (alias Hiwa).

‘SimCity’ like in Unity

Estreno la categoría de Tutoriales con un nuevo proyecto personal llamado “UnityCity” descrito anteriormente; y en el que me he propuesto, como dice el título, hacer un juego al estilo SimCity 2000, SimCity 3000 o SimCity 4; en Unity.

Comienzo detallando el sistema de colocación de objetos (o ‘props’) en el escenario.

Comenzando por tener un grid como base de escenario, me he decantado por auto-generar una serie de minicubos prefabricados de tamaño (1, 0.25, 1) llamados “losa” con la siguiente textura:

Los “instancio” a partir de las coordenadas (0, 0, 0) con un script muy simple:

Y obtengo esto:

Captura

 

Ya tengo preparado un pequeño “grid” donde poder trastear con edificios, calles, etc…

Ahora, creo un .prefab con un par de cubos, que simulen una comisaria (o un hospital, o un colegio, o whatever…) al que llamo “edif_Test”, con un tamaño total máximo de (1, y, 1), con y un valor cualquiera (ya que es la altura del edficio).

Capturaedif Capturaedif2

Este prefab deberá anclarse a la casilla del suelo al hacer click sobre la misma. Para ello, hago uso de los famosos Raycast

Creo otro script con el siguiente código:

En este código preparo el típico Ray y RaycastHit para detectar dónde hago click. Al comenzar, cargo como recurso el prefab previamente creado del edificio en cuestión.

Mediante el método Camera.main.ScreenPointToRay(Input.mousePosition); lanzo un raycast desde la posición del ratón hacia la dirección en la que mira en la cámara. De este modo, con la cámara en modo Ortographic, donde pongo el puntero es donde pongo el edificio.

En caso de que el Raycast detecte físicas (en este caso, el grid del mapa), mediante el método Debug.DrawRay, puedo comprobar como efectivamente, la posición del puntero coincide con el lugar que señalo (aunque no se aprecia demasiado, el Debug.DrawRay es la delgada línea roja [peliculón!])

raycast_example_unitycity

Al definir

, lo que estoy haciendo es obtener las coordenadas ‘x’ y ‘z’ del centro del cuadradito del grid; de modo que al instanciar el edificio; éste aparezca justo en el centro del cuadrado.

Ya sólo queda entonces que, al hacer click, aparezca el dichoso edificio, en la posición definida:

Simple, rápido y eficaz. Ya tengo la base de UnityCity

unitycity_prev

UnityCity – Idea & Vision

Harto de modernas versiones de creadores y gestores de ciudades (como SimCity 2013, Cities XL…), juegos de complejidad extrema (o absolutamente todo lo contrario), mal rendimiento, y acabado tosco o insatisfactorio; me propongo hacer un proyecto que recoja la esencia de auténticos clásicos en lo que a gestión urbanística se refiere (véase Caesar, Pharaoh, o el glorioso SimCity 4).

Para comenzar, estudio una serie de requisitos que detallaré más adelante en la ficha informativa UnityCity, comenzando por lo más básico: la colocación de ‘props’ y edificios.

Para ello, me he decantado por el estilo clásico de los juegos anteriormente mencionados, dividiendo el escenario en un grid de cuadrados, con una cámara isométrica (giratoria 360º); y evitando dejar esos tan incómodos huecos vacíos.

Que dé comienzo el diario de desarrolo de ‘UnityCity’!

Steam Workshop – Umbrella Hat (TF2)

Umbrella Hat (Team Coloured)

Mi primer modelo para el workshop de Steam fue este sombrero para Team Fortress 2.

No ha sido ni será aprobado, ya que hay uno muy parecido dentro del juego, pero al menos me sirvió para familiarizarme con el proceso de creación y publicación del item, mediante las tools del Source SDK 2007.

Hecho en 3D Studio Max 2012, con un porrón de polígonos y colores pastel (luego más tarde me enteré según la guía que Valve proporciona a desarrolladores, que el máximo de polys recomendados son 1k).

Just backed 10$ @ Kickstarter

No suelo gastarme el dinero por vicio en Kickstarter (famosa web de crowfunding por supporters que casi “backean” proyectos por deporte), pero para el caso de este juego he hecho una excepción y he aportado mis 10$.

El juego en cuestión se titula “Red Goddess“, y esta hecho por un pequeño estudio indie español llamado Yanim Studio.

La historia trata de una joven diosa que ha perdido todos sus poderes y tiene que recuperar la memoria dentro de su subconsciente.




Una de las características más curiosas del juego, es que, para derrocar enemigos, la pelirroja protagonista deberá adentrarse en el interior de estos, y completar puzzles con el uso de sus habilidades.

La mecánica de estas habilidades se basará en que puede dividirse en forma de elementos (hielo y fuego).

Sinceramente, me parece una apuesta nacional muy curiosa y entretenida, además de tener un característico y cuidado estilo visual. Si la campaña sale bien, el juego verá la luz en Enero del año de 2015.
A priori parece una fecha un poco lejana, pero es un período de tiempo justo y aceptable, para que este grupo de desarrollo indie pueda cuidar y pulir hasta el más mínimo detalle.

Éste es el enlace a la campaña de Kickstarter: https://www.kickstarter.com/projects/yanimstudio/red-goddess?ref=card

Y éste el enlace a la propuesta del juego en Greenlight: http://steamcommunity.com/sharedfiles/filedetails/?id=225684478

[///] – Día II (Player)

Antes de empezar se debe tener muy claro el flujo de trabajo a la hora de hacer el proyecto. En este caso, he decidido primero hacer un nivel jugable, con unos modelos muy básicos (sin detalles, ni texturas, ni sombras). Tan sólo el concepto de jugabilidad y dificultad ante la IA.

Una vez terminado este paso, ya llegará el momento de adornarlo todo con detalles.

Empiezo con el player, y para ello, creo un rectángulo básico que representa al cañon. Este GameObject lleva añadido un Box Collider, que hará de cuerpo detector de los disparos enemigos.

 

Hay que tener en cuenta que la posición de este “collider” no es la inicial (0,0,0); ya que se presupone, representa a una nave espacial, y el cañón en si, una parte de esta nave.

 

Luego, la cámara principal del juego ira enganchada a este cañón, de manera que se posicione en medio de la imagen de la misma, gire hacia donde gire.

 

Dejo por aquí una captura de las propiedades de este gameobject llamado “Cannon”, con las coordenadas del Box Collider.

El Rigidbody añadido al cañon tiene bloqueado tanto rotaciones como posición, en XYZ.
“PlayerCol” es el tag para el collider del player, de manera que cuando programe los disparos de los enemigos, si colisionan con “PlayerCol”, el jugador debe perder 1 barra de vida.

De la animación y el script añadidos hablaré más adelante.

[///] – Día I (Papel y boli)

Los requisitos tomados los plasmo primero en papel, antes de tomar ninguna decisión sobre el modelo de desarrollo o los prefabs a crear.

El player básicamente se compondrá por un rigidBody con posiciones x,y,z fijadas en el espacio y rotación libre, cañón que lanzará “ammo” (disparos), una cámara acoplada y una esfera sin renderizar que servirá como collisionTrigger para activar los disparos de los enemigos. El radio de dicha esfera determinará la distancia desde la que el enemigo comenzará a disparar.

Los enemigos tendrán un límite de velocidad en valores absolutos (no importa la dirección que tomen), de manera que podrán acelerar y desacelerar sin superar un límite establecido, conectados mediante springJoints al rigidBody del player.

El que el enemigo dispare a partir de cierto límite de “cercanía” del player es un hándicap en la jugabilidad. Pero otro mucho más importante es el grado de puntería a la hora de disparar al jugador.

Para esto, como el enemigo siempre avanzará de frente (es decir, aunque tome giros o elipses en torno al player, el modelo de enemigo siempre estará mirando hacia delante), el vector que seguirán sus disparos sera la variable predefinida Vector3.forward con respecto a él mismo. Es a éste vector (eje-Z en el dibujo) al que le aplico un “offset”. Para ello, obteniendo un número random en un rango determinado, se multiplica al valor del vector y el tiro se desviará en función de dicho número random.

Por tanto, para obtener mayor dificultad (el enemigo falla menos disparos), tan sólo hay que disminuir el valor del offset; y para obtener el resultado contrario, aumentarlo.
En la parte inferior del papel plasmo la idea de una posible segunda IA “aliada” con el player, que en caso de entrar en un trigger esférico del enemigo, dispare a éste.
Al no ser una idea crítica para la jugabilidad principal, la pospongo para más adelante y la dejo ahí apuntada.

En esta última página muestro un concepto de GUI. Los enemigos se verán marcados por dos corchetes [ ] que se moverán por la pantalla en una posición relativa a la cámara del player (más adelante explico el código y conversión matemática de los valores de la posición del enemigo respecto a los del GUI por la pantalla, ya que los de éste último deben variar entre 0 y 1.
Encima del modelo del enemigo aparecen los números 3/3. Estos números determinan la cantidad de disparos necesarios para eliminar al enemigo. Más tarde, una vez implementada la GUI en Unity, decidí [spoiler=desechar esta idea][img]http://i.imgur.com/aMbMmbd.jpg[/img][/spoiler] y usar barras de vida [ /// ] (lo que da lugar a este proyectillo), de modo que por cada disparo acertado se elimina una barra.
También estudio la posibilidad de cambiar el color de esta GUI en función de la cercanía al player, de modo que los enemigos más cercanos al player (y potencialmente peligrosos y al mismo tiempo fáciles de derribar) se marquen en rojo.

[///] – Requisitos y brainstorming

[///] será un minijuego con naves espaciales enemigas que tengan IA propia y disparen al jugador, que estas naves nunca se muevan 2 veces iguales, y que el comportamiento de cada una sea distinto al de las demás.
El jugador, desde una posición estática, deberá destruir todas estas naves controladas por la IA.

En principio, parece un planteamiento sencillo para implementar. El principal problema a abordar es el de la IA propia de los enemigos, el que cada uno sea único y diferente a los demás, y que encima no se muevan iguales cada nueva partida.

Aunque el jugador mantenga una posición estática, le voy a poner una vista en 1ª persona de una torreta, que pueda girar 360º en el eje-X, y una limitación de +-75º para el eje-Y. Los controles serán con un ratón y opcionalmente teclado (no descarto uso de joysticks/gamepads).

El “respawn” de enemigos será instantáneo (por ahora). Una única escena donde existan entre 20 y 25 enemigos que ataquen al jugador, y éste deba defenderse y derribarlos.

El juego será totalmente en 3D
Engine: Unity
Plataforma: PC/Webplayer

No habrá límite de tiempo para la demo. El jugador tiene 5 puntos de vida, cada disparo que reciba de la IA enemiga le restará 1 punto, y podrá recuperar 1 punto de vida por cada nave destruida. Cada nave enemiga dispondrá de 3 puntos de vida, por lo que será necesario acertar con 3 disparos.

[b][[WARNING: Posible escalón insalvable en nivel de dificultad]][/b]

Si la probabilidad de recibir disparos es mayor que destruir enemigos, se estudiará la posibilidad de añadir “un tipo de escudo de energia” con el que el jugador pueda protegerse de los disparos enemigos. Los factores generales que determinan la dificultad serán:

– Velocidad movimiento IA enemiga
– Velocidad movimiento disparo jugador
– Cantidad ráfaga disparos IA enemiga
– Cantidad ráfaga disparos jugador
– Distancia (lejanía) disparo IA enemiga
– Alcance disparo jugador
– HP IA enemiga
– HP jugador