miércoles, 3 de septiembre de 2014

Implementación de la cámara

Después de hablar de un plugin de splines de Unity, usos que le di y hablar de forma más teórica sobre los distintos tipos de cámara que se pueden dar en un juego, llega el momento de que cuente qué cámara quiero, cómo la plantee y qué problemas me dio.



¿Qué tipo de cámara quería? Sobre raíles. Me parece más fácil para el jugador este tipo de cámara, el juego no tiene componente de exploración, así que solo serviría para complicar los controles. De esta forma también tengo la posibilidad de en tiempo de diseño de nivel decidir qué enseño y qué no al jugador. Aunque esto también complica esa fase, es una de las fases que más quiero aprender, así que me va bien. Además de cara a que el juego pueda funcionar en dispositivos móviles creo que ayuda a que los controles sobre pantalla táctil no se compliquen.



Como ya he dicho mi modelo de cámara era el de Crash Bandicoot 3, pero llegaba el momento de implementarla. La que viene por defecto con el obrero de Unity, y por lo tanto base para crear un personaje 3D es de las que van siempre a la espalda del personaje y giran con él.




La primera tentación es la de crear una cámara muy sencilla que funcione rodando por un eje. Por ejemplo en el eje z, así que la posición x e y será fija en diseño y la posición en z será la del personaje, un poco más retrasado. Es una forma sencilla de implementar, y tienes un rail a lo largo de z, se podría hacer para cualquier eje y dirección. Pero ese es el problema, estás obligado a que sean ejes para que sea tan sencillo. Si en tiempo de diseño quieres un corredor en 15º, la cámara no mirará a lo largo del corredor al no ser perpendicular a los ejes. Es una restricción demasiado fuerte para el diseño.



Aunque ya tenía algo de experiencia usando splines como rutas para la cámara por la práctica de la montaña rusa en OpenGL hacerlo a mano, y que funcionase como quería como cámara en tercera persona iba a ser mucho trabajo, por eso, después de ver lo que iTween Path podía hacer decidí usarlo para la cámara. Pero todavía quedaban cosas por resolver.



Una vez que se tiene una ruta en forma de spline hay que pensar cómo calcular en que posición del spline debería estar la cámara según donde esté el personaje. La solución que tomé, intentar dividir los splines en trozos más pequeños, a ser posible parábolas, aunque si uso algunos de 4 o 5 nodos. Entonces, cometiendo un pequeño error, tomar como recta la unión entre el primer y último nodo (línea azul claro). Entonces proyectar (azul oscuro) la posición del personaje (cruz roja), sobre la línea anterior. La longitud de la proyección en esa línea, será la que tomemos como distancia del personaje. Los splines funcionan parámetricamente con un parámetro [0-1], así que la distancia de la línea que une los nodos la tomo como uno, y la distancia que tomo que tiene el personaje al nodo inicial será una fracción menor que uno.



Realmente estoy tomando la posición del personaje, teniendo únicamente en cuenta su posición en el eje que une los nodos extremo del spline. Funciona bien si el spline no es muy curvado ni hace cosas raras, para que la aproximación de la unión de los nodos extremos por longitud del spline sea aceptable (probé a hacerlo con la longitud real del spline, iTween la calcula, pero funcionaba peor).



Por la forma de tomar la posición del personaje la cámara solo avanza o retrocede si se mueve en la dirección del spline, pero se queda en el mismo sitio si el jugador mueve solo a la izquierda o la derecha. Esto hace que si el escenario es demasiado ancho el personaje pueda salir fuera de lo que se ve en pantalla. Para resolver este problema y no tener tanto problema de diseño en los escenarios decidí que la cámara girase siguiendo siempre al jugador, de tal forma que siempre estuviera centrado en la imagen, pero solo se moviera a lo largo de la ruta marcada. 


Esto sería para un trozo, pero en realidad hay varios, y hay que hacer bien el empalme entre ellos. Si en diseño tienes cuidado y pones el inicio de un trozo como el final del anterior y con una orientación parecida (no hace falta que sea C1) solo hay que saltar al siguiente spline con posición 0 cuando lleguemos a la posición 1 del actual. Pero no es tan sencillo, porque la posición de la cámara no es exactamente la del jugador. La cámara la retraso una distancia fija en coordenadas del spline, pero dependiendo de la longitud de éste. Por ejemplo en un spline de longitud 100 la distancia será de 0.08, pero en uno de 200 será de 0.16, por poner un ejemplo. Siempre hablando de distancias entre [0,1]. Entonces el problema lo tenemos en que aunque el personaje haya pasado ya al siguiente spline, la cámara sigue en el anterior. Por lo que estamos extrapolando su posición más allá del límite de ese spline. Yendo hacia atrás nos puede pasar lo contrario, que al restar esa distancia de cámara, de menos que 0, por lo que debemos ir yendo al spline anterior. El sistema así tomado funciona bastante bien.



Y todo lo contado aquí suena bastante bien, parece que teniendo cuidado con algunas cosas, la implementación hecha, aunque tenga errores por simplificación, funciona bastante bien. Y así lo creía, en mis primeras pruebas quedé muy contento con la cámara. No fue hasta que la puse a prueba del todo, haciendo los diseños de los niveles, y los jugué mucho que comencé a ver los problemas que daba. Eso será para el siguiente artículo. 

No hay comentarios :

Publicar un comentario