En el último artículo dejamos al
personaje
moviéndose por la escena. Quería como siguiente paso ver si era
capaz de hacer una de las partes que tenía hechas en el
SuperCharacterController pero no integradas en mi proyecto, las
referentes al cambio de gravedad.
Al ser un ejercicio académico lo más
importante aquí es aprender. Por eso aunque el trabajo realizado en
los cambios del controlador de personaje anterior no se va a usar en
el juego final, todo lo que me tuve que pegar con los giros,
cuaternios y direcciones de la gravedad me sirvió para aprender y
poder realizarlo en el nuevo controlador en menos tiempo. Incluso
algunas de las funciones, como la que calcula los ejes más cercanos
a un vector las he podido reutilizar.
No encontré ninguna animación que me encajase bien para el cambio de gravedad, así que acabé haciéndola a mano. Es sencilla, como un salto con ambos pies y abrir los brazos mientras gira la gravedad. Dividida en dos animaciones, la parte de ascender y la de girar. Así la máquina de estados de Mecanim me dará los dos estados que necesito para controlarlo en el código.
En la primera versión tenía dentro de
la animación la ascensión, y lo único que tenía que controlar por
código era el giro. Y esa parte en concreto no es tan difícil, se
calcula un cuaternio que represente la rotación deseada al final, y
se interpola en cada paso el pequeño giro a dar, teniendo ya hecha
la función que compara dos cuaternios para saber cuando hemos
llegado lo suficientemente cerca para hacer un último paso de giro
poniendo la rotación definitiva.
Más complicado es hacer que el
personaje se mueva correctamente con la nueva gravedad. Al finalizar
el giro cambio la gravedad global de Unity, por lo que en teoría
tendría que afectar a obstáculos, enemigos... o eso espero. El
script de control de personaje tenía algunas partes donde usaba
cosas ajenas a esa gravedad, siempre en el eje Y, por lo que si tu
gravedad está en otro eje, u otra dirección no funciona bien. Así
que le tuve que meter mano. Y fue seguramente la parte más
complicada. En el controlador anterior todo estaba calculado más a
mano, aquí se usan funciones internas de Unity, del tipo de
InverseTransformDirection o ProjectOnPlane, que está documentado lo
que hacen, pero no explica muy bien cómo lo hace, por lo que no se
si está teniendo en cuenta algunas cosas predefinidas como si arriba
es Y, cosa que en mi caso no tiene porqué cumplirse. Aún así, a
base de pruebas de datos, y con un sistema de matrices de permutación
para varias las direcciones en una de las etapas conseguí que
funcionase bien. Siempre y cuando la cámara gire junto al personaje,
ya que lo que significa “hacia delante” o “derecha” va ligado
a la cámara, a lo que ve el jugador. Por eso para las pruebas he
hecho que la cámara cuelgue directamente del personaje, así gira
con él, a falta de hacer más adelante un sistema de cámara más
complejo para los giros que dependa del sistema de cámara sobre
raíles que he estado creando.
Como he dicho el movimiento de ascender
y una leve levitación estaban hechos directamente en la animación,
pero por alguna razón la capsula del personaje no se movía con esa
animación. Esto provocaba que si girabas cerca de una pared la
cabeza no quedase cubierta por la capsula que calcula las colisiones
y la cabeza atravesase la pared. Entonces me acordé de que en el
tutorial de mecanim que había seguido se trataba un problema
parecido. Creaban una curva en la animación con la altura de la
cápsula para que se adaptase al personaje cuando se hacía una bola
al saltar, y en el código iban adaptando la altura de la capsula con
los datos de la curva. Así que hice lo mismo, crear una curva para
cambiar la posición Y de la capsula, y que esta se adapte a la
posición del personaje. El resultado no fue el esperado, por alguna
razón, al subir la cápsula, el cuerpo del personaje, la malla
bajaba, y sigo sin saber bien qué controla ese movimiento, sospecho
que algo interno de Mecanim. El caso es que no conseguí que
funcionase así.
La solución que dí a este problema
fue quitar ese movimiento de las animaciones. Es decir ahora en la
animación se ve como coge impulso, y abre los brazos durante el
giro, pero ni se eleva ni gira, todos esos movimientos se harán por
código. Y aquí viene una nueva duda. ¿cómo elevar el personaje,
cuando debe elevarse, y no antes? Porque la animación primero dobla
las rodillas para coger impulso, debería elevarse una vez que se ha
vuelto a estirar. Intenté hacerlo con curvas, pero el resultado no
fue bueno, ya que la curva te da un valor en cada momento, y no puedo
dar un valor absoluto a la Y del personaje, así que puedo ir sumando
el valor de la curva a su posición Y (es local, no me preocupa la
gravedad), pero al finalizar el ascenso el personaje cae, y la forma
en que sube no es buena. Cambié la curva por un evento sobre la
animación, otro tipo de cosa que no había probado. Marcas un
momento en el que quieres que se ejecute algo, script y función y
hasta parámetros si quieres. Así que hice que ejecutase una función
justo al finalizar la parte de la animación donde coge impulso, para
dar impulso al rigidbody del personaje, igual que cuando se salta.
Aunque haciéndolo así, caería mientras gira, por lo que hice que
la gravedad fuera 0 durante el giro, para comenzar con la nueva
gravedad una vez completado.
Con eso ya tengo el giro correcto del
personaje y que funcione bien, ahora solo falta poner unos efectos
especiales, ponerlo bonito. Quería algo que pareciese un poder del
personaje y que se propagase el resto del escenario. He probado los
sistemas de partículas que vienen en Unity 5, y algunos de la Asset
Store, los he combinado y personalizado. De los de Unity 5 he cogido
un subemisor del de explosiones que hace como una onda expansiva.
Pero he cambiado de billboard a malla con una esfera. Y de uno de la
asset store que es como una magia verde, he cambiado los sprites a
azul. Usa un sistema bastante curioso donde se usa una textura con
varios sprites y va cambiando de uno a otro, es parecido a trabajar
con sprites en 2D o CSS sprites para los que vengan del diseño web.
También he quitado sub-emisores y personalizado otros. Y venía con
dos luces, me he quedado solo 1 y simplificándola, pero queda bien,
da más luz durante el uso de las partículas. Luego he separado todo
este lio en 2 sistemas distintos, para poder apagar uno (el de la
luz) y que las partículas del otro (las ondas expansivas) no
desaparecieran. Con un poco de paciencia, ajustando bien las cosas y
eventos, conseguí que quedase bien, es lo que se ve en el vídeo.
No hay comentarios :
Publicar un comentario