Vista previa del material en texto
Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 1 Programación de Video Juegos con Unity. Nivel Avanzado. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 2 Módulo 1: Prototipado Unidad 1: Física de Personajes y Proyectiles Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 3 Presentación: Bienvenidos al Nivel Avanzado del curso de Unity. Espero que lo aprendido les esté ayudando a expresar su creatividad a través de este apasionante mundo, tanto como yo aprendo de ustedes con sus dudas y sugerencias. En este nivel potenciaremos las capacidades aprendidas en nivel anterior, aprendiendo herramientas avanzadas del sistema de Unity, todo con el objetivo de poder hacer un juego del estilo FPS o First Person Shooter (Disparador en Primera Persona). Ejemplos de este tipo de juegos pueden ser DOOM, Quake, Counter-Strike, etc. En esta unidad comenzamos a ver cómo movernos y disparar. Ustedes dirán que ya vimos eso en el nivel anterior, pero en un juego de tipo FPS hay una serie de diferencias y requisitos con respecto al juego que hicimos anteriormente. Eso no significa que todo lo que vimos antes no sirve para un FPS, si no que necesitamos nuevas herramientas para superar el desafío de un juego más complejo. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 4 Objetivos: Que los participantes aprendan a combinar diversos conceptos para crear: Un controlador de tipo FPS. Una cámara de tipo FPS. Un disparador de tipo FPS. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 5 Bloques temáticos: Cámara. Movimiento. Disparo. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 6 Consignas para el aprendizaje colaborativo En esta Unidad los participantes se encontrarán con diferentes tipos de actividades que, en el marco de los fundamentos del MEC*, los referenciarán a tres comunidades de aprendizaje, que pondremos en funcionamiento en esta instancia de formación, a los efectos de aprovecharlas pedagógicamente: Los foros proactivos asociados a cada una de las unidades. La Web 2.0. Los contextos de desempeño de los participantes. Es importante que todos los participantes realicen algunas de las actividades sugeridas y compartan en los foros los resultados obtenidos. Además, también se propondrán reflexiones, notas especiales y vinculaciones a bibliografía y sitios web. El carácter constructivista y colaborativo del MEC nos exige que todas las actividades realizadas por los participantes sean compartidas en los foros. * El MEC es el modelo de E-learning colaborativo de nuestro Centro. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 7 Tomen nota: Las actividades son opcionales y pueden realizarse en forma individual, pero siempre es deseable que se las realice en equipo, con la finalidad de estimular y favorecer el trabajo colaborativo y el aprendizaje entre pares. Tenga en cuenta que, si bien las actividades son opcionales, su realización es de vital importancia para el logro de los objetivos de aprendizaje de esta instancia de formación. Si su tiempo no le permite realizar todas las actividades, por lo menos realice alguna, es fundamental que lo haga. Si cada uno de los participantes realiza alguna, el foro, que es una instancia clave en este tipo de cursos, tendrá una actividad muy enriquecedora. Asimismo, también tengan en cuenta cuando trabajen en la Web, que en ella hay de todo, cosas excelentes, muy buenas, buenas, regulares, malas y muy malas. Por eso, es necesario aplicar filtros críticos para que las investigaciones y búsquedas se encaminen a la excelencia. Si tienen dudas con alguno de los datos recolectados, no dejen de consultar al profesor-tutor. También aprovechen en el foro proactivo las opiniones de sus compañeros de curso y colegas. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 8 Cámara Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 9 Viendo en primera persona Comencemos viendo la primera diferencia entre un juego FPS y un Top-down Shooter (disparador de cámara superior, como el que hicimos la unidad pasada), y esta sería la cámara. En el nivel anterior no necesitábamos mucho de ella, con que este quieta mirando al lugar correcto alcanzaba, mientras que en un FPS necesitamos que la cámara se mueva según donde el jugador mire. Veamos cómo. Emparentamiento Anteriormente el personaje se movía, pero la cámara se quedaba quieta, comportamiento deseable y esperado al tener dos objetos separados, pero hay otras situaciones en las cuales esperamos otra reacción. En estas situaciones deseamos que un objeto este alineado con otro, también conocido como “emparentado”. Ejemplos de esta situación puede ser el caso de equiparse objetos al personaje, como ponerse un sombrero y que este esté fijo en la cabeza, o ponerse unas botas y que sigan a los pies, hasta el caso de ponerse un arma y que esté fija en la mano. Cuando un objeto “H” está emparentado al objeto “P” se considera hijo del objeto P, por ende, H se mueve, rota y se escala junto a P. Vimos algo al respecto anteriormente cuando visitamos GUI, donde teníamos un objeto Canvas y varios objetos dentro de él, como botones, texto e imágenes. En ese caso dichos objetos serian hijos del objeto Canvas, cosa que también indica que un objeto Padre puede tener muchos objetos Hijo. Para comprender mejor esto repasemos la forma de emparentar objetos, la cual consta simplemente de arrastrar el objeto que deseamos que sea hijo al objeto padre desde el panel de Hierarchy. Como vemos, Unity nos indica que un objeto es hijo de otro poniendo una flecha al lado del objeto padre, y poniendo al hijo debajo del objeto padre, espaciado un poco hacia la derecha. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 10 La flecha al lado del padre sirve para ocultar y mostrar los hijos. Cuando la misma está apuntando hacia abajo, indica que los hijos son visibles, mientras que si apunta a la derecha indica que los hijos están ocultos. Para cambiar esto simplemente hacemos clic en la flecha. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 11 Ejercicio N°1 Crear cuatro objetos vacios llamados “Brazo”, “Antebrazo”, “Mano” y “Espada”. Emparentarlos de forma tal que la “Espada” sea hijo de “Mano”, “Mano” de “Antebrazo” y “Antebrazo” de“Brazo”. Ejercicio N°2 Crear tres objetos vacios llamados “Anillo1”, “Anillo2” y “Pulsera”. Emparentarlos de forma tal que “Anillo1” y “Anillo2” sean hijos de “Mano” y “Pulsera” de “Brazo”. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 12 Posición Relativa En la escuela cuando nos hablaron de ejes cartesianos aprendimos que la posición de un objeto es relativa al punto central del sistema. Si un objeto está en la posición (6,2), esto significa que está a 6 unidades yendo en la dirección del eje X y 2 sobre la del eje Y. Esto se conoce como que el objeto esta en el “Sistema de Coordenadas Global”. Cuando un objeto es hijo de otro se encuentra fuera del Sistema de Coordenadas Global, y pasa a estar en el “Sistema de Coordenadas Local” del padre. Esto implica que el punto central pasa a ser la posición del padre y si el padre se mueve nos movemos, pero sin cambiar nuestro valor posición en el transform, por lo que nuestra posición es “relativa”. Tomemos el ejemplo de un auto. Nosotros estamos sentados en el asiento, por lo que estaríamos emparentados al asiento. Si el auto se mueve se mueve el asiento, y por ende nosotros, por más que nuestra posición con respecto al asiento se mantenga. El auto está emparentado al mundo, y el mundo claramente se mueve, por ende, mueve al auto, y a nosotros. El mundo gira con respecto al sol, el sol con respecto a la vía láctea, etc. Entonces por eso se dice que un objeto tiene posición relativa a su padre, porque su posición comienza desde la posición del padre. Si un objeto no tiene padre, su posición comienza desde el centro del mundo. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 13 Ejercicio N°3 Crear un cubo y cuatro cilindros. Estirar el cubo para que parezca el cuerpo de un auto, y los cilindros para que parezcan ruedas del mismo. Emparentar los cilindros al cuerpo del auto y moverlos para posicionarlos como ruedas. Mover el cuerpo del auto y ver como las ruedas se mueven junto a él. Ejercicio N°4 Crear 4 cilindros y estirarlos para que parezcan pinches (si se consigue un modelo 3D de cono mejor). Emparentarlos en las ruedas y posicionarlos como pinches de las mismas. Mover el auto y ver como se mueve todo junto a él. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 14 Rotación del Padre Nuestra posición depende de la de nuestro padre, pero no es lo único que nos afecta. En el ejemplo del auto hablamos de que está dentro del mundo y el mundo se mueve, pero también rota y esta rotación también nos afecta. Esto se debe a que nuestra posición no solo es relativa a nuestro padre, sino también a su orientación, ya que, al rotar nuestro padre rotan sus ejes. Decir que estamos en la posición (6,0) implica estar a 6 unidades sobre el eje X con respecto al centro del padre, y si el mismo esta rotado, el eje X también, por lo que apunta a otro lado. Entonces, si el mundo se quedase quieto, pero siguiese rotando, nuestra posición también se vería afectada, ya que los ejes cambian su dirección, o también, cuando el auto gira en una esquina, nuestra posición también cambia. Y cuando rota nuestro padre, no solo cambia nuestra posición sino también la rotación, ya que la rotación también es relativa. Escala del Padre Ya vimos dos de las tres transformaciones de un objeto, falta la tercera que sería la escala. Como sabemos la misma sirve para cambiar las dimensiones del objeto, estirándolo sobre sus ejes. Si nosotros escalamos nuestro padre también cambia el tamaño de sus ejes. Un objeto con escala (1,1,1) tiene sus ejes con un largo de 1 unidad (normalmente un metro), pero si lo escalamos a (2,2,2), los ejes tienen un tamaño de 2 unidades. Esto implica que si nuestra posición es (2,2,2), pero nuestro padre esta escalado a (3,3,3) los largos de sus ejes valen 3. Entonces moverse dos unidades sobre un eje de largo 3 sería lo mismo que moverse 6, por ende, nuestra posición seria (6,6,6). Esto se va a aclarar un poco mas con los ejercicios a continuación. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 15 Ejercicio N°5 Rotar las ruedas del auto hecho en el ejercicio anterior y ver como los pinches se mueven. Rotar el auto del ejercicio anterior y ver como se mueven las ruedas y los pinches Ejercicio N°6 Crear un tanque con un cubo que represente el cuerpo, otro que represente la cúpula y que este emparentado al cuerpo, y un cilindro que represente el cañón y que este emparentado a la cúpula. Rotar la cúpula y ver como se mueve el cañón. Rotar el tanque y ver como se mueve la cúpula y el cañón. Ejercicio N°7 Escalar el tanque y el auto de los ejercicios anteriores y ver como se escalan también los hijos. Escalar las ruedas del auto y ver como se escalan los pinches. Escalar la cúpula del tanque y ver como se escala el cañón. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 16 Cambio de Pivot Si creamos un cubo y lo rotamos, vemos como el mismo rota con respecto a su centro, pero ¿Porque no rota con respecto a una esquina? ¿o con respecto a un lado? Esto se debe a que todo objeto tiene un pivot, o sea, un centro, y que el mismo viene definido desde el modelo 3D. O sea que, si modificamos desde el modelo 3D el pivot del cubo para que sea una esquina, y en Unity rotamos el objeto, va a rotar desde la esquina en vez de desde el centro. Algo de esto vimos cuando vimos GUI, al mover el circulo azul que todo objeto tenia y ver como cambiaba su eje de rotación, pero lamentablemente no tenemos dicho circulo cuando hablamos de objeto 3D, para ello tenemos otra solución. Simplemente creamos un objeto vacío y emparentamos el objeto a cambiar el pivot dentro de él. El objeto al ser relativo al padre vemos que, si rotamos el objeto padre, el objeto hijo gira alrededor del centro del objeto padre, por lo que podríamos decir que el padre seria el nuevo pivot del objeto hijo. En este caso creamos un objeto vacio que actúe como padre del cubo, movemos el cubo para que su esquina quede alineada al centro del padre y lo rotamos. Esto es muy útil a la para cambiar el pivot original de un modelo 3D al cual no podemos modificarlo. Por ejemplo, su conseguimos el modelo de un auto cuyo pivot se encuentra en el techo, probablemente queramos cambiarlo para que este en el piso, por lo que emparentaríamos el auto en un objeto vacio y lo moveríamos. Otro uso que tiene es cuando un objeto viene mal orientado para Unity. Por ejemplo, si bajamos una nave y el frente de la nave está mirando hacia el eje Y, veríamos a la nave mirando hacia arriba, por lo que una solución seria poner la nave dentro de un objeto vacío y rotarla. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148www.sceu.frba.utn.edu.ar/e-learning 17 Ejercicio N°8 Crear un cubo y emparentarlo a un objeto vacio para hacer que su pivot este en el centro de la cara inferior. Realizar el mismo procedimiento con un cilindro y una esfera. Ejercicio N°9 Crear un cilindro y emparentarlo dentro de un objeto. Rotar el cilindro de forma tal que en vez de estar parado este recostado. Ver como el eje Y del hijo está alineado al eje Z del padre, de forma tal que si tenemos el padre con rotación (0,0,0) vemos al cilindro recostado. Mover el cilindro para que el pivot del padre este en su parte inferior. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 18 Cámara en tercera persona Ahora que sabemos cómo emparentar objetos, podemos emparentar la cámara dentro del personaje, y entonces el personaje al moverse movería la cámara. Si tomamos el ejemplo donde creamos un cubo el cual lo movíamos para adelante y para atrás, y rotábamos hacia la izquierda y derecha con las flechas del teclado, y a dicho cubo le emparentamos la cámara, moviéndola para que se encuentre detrás del objeto y mirando hacia él, ya tenemos una cámara en tercera persona. Rotando la cámara Ahora que tenemos la cámara dentro del personaje, quedaría poder moverla con el mouse, esto lo podemos hacer usando ejes de input (Input.GetAxis). Recordemos que los ejes del input que representan al mouse se llaman “Mouse X” y “Mouse Y” (ver el Input Manager). Entonces, para rotar un objeto con el mouse podríamos hacer lo siguiente. Si quisiéramos podríamos aplicar las dos rotaciones del mouse en un solo componente y agregárselo a la cámara, los invito a probar y ver el resultado. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 19 EjercicioN°10 Crear un cubo y emparentar la cámara poniéndola de forma que este ubicada detrás del cubo y mirando al mismo. Agregarle un componente a la cámara que la rote usando los ejes del mouse, rotando con el eje x del mouse (“Mouse X”) el eje Y del objeto, y con el eje y del mouse (“Mouse Y”) el eje X del objeto. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 20 Vemos claramente que no es el comportamiento deseado. Esto se debe a que como “transform.Rotate” rota con respecto a las coordenadas del propio objeto, cuando nosotros rotamos el eje X, rota el eje Y, cambiando hacia donde rota el mismo. Mas allá de ese problema hay otro error de concepto ya que en un juego en primera persona, cuando movemos el mouse hacia los lados no se mueve la cabeza, sino el cuerpo entero. Por lo que el movimiento del eje x del mouse debería rotar al personaje entero, y el movimiento del eje y del mouse solamente debería rotar la cámara en el eje x, haciendo que cuando movamos el mouse verticalmente se mueva de igual forma. En resumen, el movimiento horizontal del mouse tiene que rotar al personaje entero horizontalmente, y el movimiento vertical del mouse debe mover solamente a la cámara emparentada al personaje de forma vertical. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 21 Ejercicio N°11 Crear dos componentes, uno que rote al objeto horizontalmente (eje Y del objeto) con el movimiento horizontal del mouse (“Mouse X”) y otro que rote al objeto verticalmente (eje X) con el movimiento vertical del mouse (“Mouse Y”). Agregar el componente de movimiento horizontal al cubo del ejemplo anterior, y el de vertical a la cámara emparentada al cubo. EjercicioN°12 Agregar a la cúpula del tanque de los ejercicios anteriores el componente de movimiento horizontal y al cañón el del movimiento vertical. Ver como el cañón rota con respecto a su centro, en vez de su posición de encastre con la cúpula. Emparentar un objeto vacio al centro de la cúpula y el cañón al mismo. Probar nuevamente y ver que se comporta correctamente debido a que se cambio el pivot del cañón. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 22 Limitando la rotación de la cámara El problema que nos queda resolver por ultimo sería el de limitar la rotación, ya que la cámara actualmente podría dar la vuelta entera, y el cañón del tanque se puede meter dentro del cuerpo del mismo. Esto lo tenemos que resolver limitando el rango de rotación. Si repasamos lo visto en condición de victoria y derrota, vimos los operadores de comparación, los cuales podrían servir para preguntar si el ángulo de rotación esta fuera de los límites establecidos, y en tal caso corregirlo. Eso suena bien, pero preguntar por el valor de un ángulo no es siempre una buena idea, debido a un problema llamado “Gimball Lock”. Este fenómeno se produce en ciertas combinaciones de rotaciones en las cuales dos ejes rotan como si fuese un solo eje. Esto se debe a que las rotaciones internamente funcionan como círculos concéntricos donde cada circulo representa un eje, y cada eje está emparentado dentro del otro. El orden particular de emparentamiento varia según el software a utilizar, en el ejemplo de la imagen vemos como al rotar el eje X hasta el ángulo -90, el eje Z roto junto a él (ya que está emparentado al eje X) y se alineo al eje Y, provocando que ambos ejes roten al objeto de la misma forma. Ahora, ¿Porque nunca nos enteramos de este problema antes?, porque Unity lo corrige automáticamente rotando todos los ángulos para prevenir el error, por lo que es transparente para nosotros, pero hace que preguntar por los ángulos actuales no sea algo fiable, ya que cambian constantemente. Mas información con respecto a este problema en los links del material complementario. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 23 Ejercicio N°13 Crear un cubo. Desde el editor, utilizando el gizmo de rotación, rotarlo lentamente hacia abajo en el eje X y observar como cuando el ángulo llega a ser mayor a 90 los ejes Y y Z cambian de valor. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 24 Una posible solución es usar un contador, o sea, una variable que mantenga el ángulo deseado, y decirle a Unity que ponga el objeto en dicho ángulo. La diferencia radica en que si nosotros, cambiamos la rotación de un objeto Unity automáticamente la va a convertir a una rotación que solucione el problema, modificando la rotación a otra diferente, pero nosotros en nuestro contador vamos a seguir teniendo la rotación original y así saber la rotación sin la corrección. Esto lo podemos lograr de la siguiente forma. Lo que hicimos acá fue usarel operador “=” para cambiar el valor de la propiedad “transform.eulerAngles”, la cual representa la rotación del objeto en ejes X, Y, Z, a diferencia de “transform.rotation”, que lo representa en quaterniones (mas info en material complementario). Luego creamos un nuevo Vector3 (variable con 3 ejes) con la instrucción “new Vector3” y le pasamos por parámetros la rotación deseada, sin preocuparnos por el “Gimball Lock”. Una vez que Unity ejecute la rotación automáticamente la corrige. Lo único que queda seria comprobar que el ángulo no se exceda del rango deseado. Podríamos hacerlo manualmente con ifs preguntando si es menor a -90 y en tal caso volver a poner el valor en -90, o mayor a 90 y ponerlo en 90. La alternativa igual de efectiva, pero más resumida es usar la instrucción “Mathf.Clamp”, la cual recibe tres parámetros, primero el numero a limitar, segundo el valor mínimo, y tercer el valor máximo, así devolviendo el valor limitado. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 25 Ejercicio N°14 Crear un componente que rote un objeto en el eje X dentro del rango -90 a 90. Usarlo en el ejemplo del cubo con la cámara emparentada, reemplazando el componente que rotaba con transform.Rotate. Ejercicio N°15 Crear una capsula (GameObject -> 3D Object -> Capsule). Emparentar la cámara dentro de la misma, de forma tal que la cámara quede dentro de la capsula en la parte superior, a la altura de lo que sería la cabeza de la misma. Poner el script de rotación horizontal en la capsula, y el de rotación vertical limitada en la cámara. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 26 Movimiento Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 27 Moviéndose en primera persona Una vez que ya logramos tener la cámara deseada, necesitamos avanzar sobre el movimiento deseado. Si bien nosotros aprendimos a mover objetos en el nivel anterior, hay una serie de diferencias clave entre el movimiento de un Top-down Shooter y un First Person Shooter, las cuales son manejadas por el componente “CharacterController”. CharacterController Nosotros anteriormente para hacer que nuestro jugador no traspase paredes usamos Rigidbody en modo “Dinámico Bloqueador” (recuerden que dicha terminología solamente se usa dentro del curso). También vimos que dentro de las propiedades de un Rigidbody tenemos Gravedad, pero lamentablemente la misma se ve detenida por tener Drag en Infinity. Una opción sería manejar este objeto en modo “Dinámico Bloqueador Realista”, o sea, usando físicas realistas para ello, pero tendríamos el problema mencionado anteriormente cuando hablamos de física, no son adecuadas en la mayoría de las situaciones y son difíciles de manejar. Otros problemas aparte de ello es que normalmente un personaje puede subir escalones de cierta altura, cosa que con un Rigidbody no podríamos lograr ya que se chocaría con ellos, y también tenemos un límite en las pendientes que podemos subir, cosa que el Rigidbody no tendría en cuenta y subiría cualquier tipo de pendiente. Si bien todos esos problemas se pueden resolver por código, el mismo sería mucho más complejo de lo deseado, y por suerte Unity cuenta con un componente que ya lo hace por nosotros, el CharacterController. Este componente es una versión reducida del Rigidbody, la cual no aplica física, pero previene que se traspasen paredes, tiene la capacidad de subir escalones y limita la pendiente máxima que podemos subir. Otro detalle es que viene con su propio Collider en forma de Cápsula, el cual es muy utilizado a la hora de representar el cuerpo de un ser humanoide, por lo que NO es necesario que nuestro objeto posea un Collider ni Rigidbody. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 28 Veamos sus propiedades: Height, Center, Radius: Determinan el tamaño y posición de la capsula de colisión. Step Offset: La altura máxima de los escalones que puede subir. Slope Limit: El ángulo máximo de pendientes que puede subir en grados. Skin Width: Que tanto el collider puede traspasar objetos sin que se considere una colisión. Este valor sirve como colchón para que el choque contra otros objetos sea más suave. Unity recomienda que el valor sea el 10% del radio del objeto. Min Move Distance: Si queremos mover al objeto menos distancia que este valor, el objeto no se mueve. Sirve para evitar movimientos pequeños debido a imperfecciones en el código de movimiento. Por lo general 0 es un buen valor. Este componente por sí solo no hace nada, requiere que le indiquemos por código cuando deseamos movernos. Para ello el mismo posee una instrucción similar a “Translate” llamada “Move”, la cual recibe la dirección en la cual deseamos movernos, y se encarga de mover el objeto, detectar colisiones, subir escalones y controlar pendientes. Primero accedemos al componente, tanto haciendo GetComponent a nosotros mismos (recordar la optimización de esto) o por una propiedad configurable desde el editor. Una vez que tengamos una variable que se conecte al mismo, podremos hacer uso de la instrucción Move, la cual recibe por parámetros un Vector3 indicando la cantidad que nos deseamos mover en cada eje. Para ello creamos una nueva variable de tipo Vector3 con la instrucción “new Vector3” y luego cambiamos los valores de los ejes por la cantidad deseada a mover. En este caso, no le pasamos ningún parámetro a la instrucción, ya que en este caso preferimos modificar sus propiedades luego de crearlo. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 29 Ejercicio N°16 Crear una capsula, quitarle el Collider y agregar un CharacterController. Agregar un componente que rote hacia los lados y mueva hacia adelante y atrás con teclas usando la instrucción Move del CharacterController. Crear con cubos un escenario de prueba, con pendientes y escalones de diferentes alturas. Probar mover al personaje por las diferentes pendientes y escalones probando diferentes valores para “Step Offset” y “Slope Limit”. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 30 Simulando la gravedad Si realizamos el ejercicio anterior, veremos que luego de subir escalones o pendientes, el objeto no baja. El componente CharacterController no aplica gravedad, deja a decisión del programador como manejarla. Por ende, tendremos que simularla nosotros mismos. Para lograr simularla analicemos un poco la situación. La gravedad es una fuerza que nos empuja constantemente hacia el suelo. Esta fuerza a medida que pasa el tiempo se va acumulando, por ende, va creciendo la velocidad en la cual nos desplazamos hacia abajo. Cuando tocamos el suelo nos detenernos, por ende, en dicha situación la gravedad se anula. De este análisis podemos sacar las siguientes conclusiones. Primero, para simular la gravedad debemos tener una variable que almacene nuestra gravedad actual,la cual constantemente va aumentando, y dicha variable nos va a servir para saber a qué velocidad nos movemos hacia abajo. La misma al aumentar constantemente va a dar la sensación de aumento de velocidad por gravedad. Una vez hecho esto lo que quedaría es detectar si chocamos contra el suelo. Por suerte esto también lo hace el componente, a través de la propiedad “isGrounded”. La misma es un booleano que se activa o desactiva luego de ejecutar la instrucción Move, indicando si el ultimo movimiento involucro una colisión contra el suelo o no. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 31 Ejercicio N°17 Modificar el componente de movimiento anterior para agregarle gravedad. Detectar la colisión contra el suelo comprobando si la propiedad “isGrounded” está en true LUEGO de ejecutar la instrucción Move (debajo). En tal caso, anular la gravedad (igualarla a 0). Ejercicio N°18 Modificar el componente de movimiento anterior para salto. Para ello habría que cambiar el valor de la gravedad de forma tal que, en vez de empujar hacia abajo, empuje hacia arriba cuando presionemos la tecla de salto. Ejercicio N°19 Modificar el componente de movimiento anterior para saltar únicamente cuando estamos tocando el suelo. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 32 Disparo Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 33 Disparando en primera persona Ya cada vez estamos más cerca de lograr tener a nuestro personaje listo. Falta lo más importante y divertido, disparar. Se preguntarán porque volvemos a ver esto, y como se imaginarán, la respuesta es similar a las anteriores, el disparo en FPS tiene diferencias. Proyectiles Veloces Numerosas veces hemos dicho que el sistema de físicas tiene sus límites, y uno de los más importantes es a la hora de manejar objetos veloces. Cuando un objeto se mueve muy rápido, corremos el riesgo de que traspase las paredes, ya que entre frame y frame puede llegar a moverse tanto que nunca la toque. Hay soluciones a este problema, como configurar “Colisiones Continuas” en el componente Rigidbody, las cuales cambian la forma de detectar colisiones para prevenir estos errores, pero esta forma cuesta mucho más, pudiendo reducir drásticamente los FPS de nuestro juego si no la usamos correctamente. Debido a ello, no es una práctica usable a la hora de hacer disparos de balas, ya que ellas van demasiado rápido y hay demasiadas en escena. Otro detalle a tener en cuenta más allá del aspecto gráfico es que la bala de un arma, al ir tan rápido, no llega a ser visible, por lo que instanciar un objeto y moverlo a una velocidad gigante también sería un gasto de tiempo para dibujar un modelo 3d que no se va a ver, y que pronto va a ser destruido. La solución aquí seria no instanciar balas, y usar la instrucción Raycast. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 34 Instrucción Raycast Ella crea una línea imaginaria que sale desde un punto y en una dirección para saber si choco y contra que. Choca contra colliders de objetos, NO contra la forma gráfica. Si un objeto no tiene Collider, o el rayo choca contra la forma gráfica, no hay colisión. La ventaja de esta técnica es que no requiere que se cree ningún objeto, por lo que no hay que perder tiempo de proceso en ello, ni en dibujarlos, ni detectando colisiones de forma continua o eliminándolos. En vez de ello, es una simple instrucción de código que instantáneamente lanza el rayo y nos indica contra que choco, todo ello en el momento en el cual ejecutamos la instrucción. Para las balas de un arma de fuego esto es ideal, ya que, a menos que queramos hacer una simulación híper realista de un arma, la bala en un videojuego puede atravesar todo el escenario en un instante, por lo que si ejecutamos dicha instrucción en el momento en el cual apretamos la tecla, y dañamos al objeto al que choca, es perfectamente válido. La instrucción se llama “Physics.Raycast” y tiene muchas formas de ejecutarse, cada una ofreciendo diferentes niveles de información. Veamos algunas de ellas. Esta es la versión más simple, la cual recibe como primer parámetro el origen del rayo (la punta del arma en este caso), como segundo parámetro la dirección del rayo (hacia donde mira el arma) y finalmente retorna un booleano indicando si choco con algo o no. Veamos que al primer parámetro le pasamos “transform.position”, o sea, la posición del componente, y como segundo “transform.forward”, el cual representa la dirección en la cual está mirando el objeto. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 35 Ejercicio N°20 Crear un componente que dispare un rayo desde la posición donde esta (transform.position) hacia donde está mirando (transform.forward). Indicar si choco o no con un mensaje en la consola. Ejercicio N°21 Crear un componente que dispare un rayo desde la posición donde esta (transform.position) hacia arriba del objeto (transform.up). Indicar si choca encendiendo y apagando un objeto. Para ello se puede tener una referencia al objeto con una propiedad de tipo GameObject, y hacer uso de la instrucción SetActive de la misma. Ejercicio N°22 Crear un componente que mueva el objeto hacia adelante constantemente y que dispare un rayo desde la posición donde esta (transform.position) hacia donde está mirando (transform.forward). Si choca contra algo, usar “transform.Rotate” para desviar su curso. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 36 Si bien hay situaciones en las cuales con saber si algo va a chocar o no es suficiente, como saber si un objeto esta en rumbo a chocar a otro independientemente de la distancia, la mayoría de las veces necesitamos ser más específicos. Veamos la siguiente sobrecarga (forma de ejecutarlo). Esta versión recibe un tercer argumento, el cual indica hasta donde tiene que llegar el rayo, a diferencia de su versión más simple, la cual va hasta el infinito. Esta versión tiene más usos, como sensor para saber si un auto está a punto de chocar, o si un objeto está cerca del suelo, tirando un rayo corto desde sus pies hacia abajo, etc. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 37 Ejercicio N°23 Crear un componente que mueva un objeto constantemente hacia adelante y que dispare un rayo desde la posición donde esta hacia donde está mirando con una distancia máxima de 2 unidades. Si el rayo choco contra algo, tieneque quedarse quieto y rotar hasta que el rayo deje de chocar, situación en la cual tiene que volver a moverse. Esto se puede resolver simplemente usando un IF y un ELSE. Ejercicio N°24 Crear un componente que mueva un objeto hacia adelante y dispare dos rayos de 2 unidades de distancia, uno para cada uno de sus lados (“transform.right” y “-transform.right”, o sea, su derecha por -1). Si choco el rayo derecho, mover el objeto a la izquierda y viceversa. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 38 Ambas versiones tienen un problema. El rayo no sabe de qué objeto salió ni que componente lo ejecuto, por ende, no sabe que Layers tiene el objeto. Recordemos que una forma de prevenir que ciertos objetos colisionen con otros es configurando la “Layer Collision Matrix” en el Physics Manager (Edit -> Project Settings -> Physics), pero como el rayo no sabe que objeto lo lanzo, no puede filtrar la colisión. La capacidad de filtrar lo que choca el rayo es muy necesaria, ya que recordemos que quizás tenemos Colliders destinados a PowerUps o a sensores para abrir puertas, los cuales no deberían detener una bala. Veamos otra versión de Raycast que si lidia con ello. La propiedad de tipo “LayerMask” es una propiedad que permite seleccionar un conjunto de layers. Dicho conjunto al pasárselo a la instrucción Raycast le indica que solamente el rayo colisione contra esos layers, ignorando los demás. De esta forma podemos especificar desde una propiedad a cuáles layers queremos chocar y a cuáles no. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 39 Ejercicio N°25 Crear un componente que mueva un objeto hacia adelante y dispare un rayo hacia adelante para saber si tiene que continuar o rotar para esquivar el obstáculo. El mismo debe colisionar solo contra objetos que tengan el layer “Pared”, ignorando cualquier otro layer. Ejercicio N°26 Crear un componente que mueva un objeto hacia adelante y dispare dos rayos, uno de 3 unidades de distancia, otro de 2, y que solo choquen contra el layer “Pared”. Si ningún rayo choco, moverse a 5 unidades por segundo, si choco el de 3 de distancia moverse a 3, y si choco el de 2 rotar. Ejercicio N°27 Crear un componente que mueva un objeto hacia adelante y dispare dos rayos, uno que choque solo contra el layer “Pared” y el otro solo contra “Acelerador”. (Usar dos propiedades de tipo LayerMask). Si choco contra Pared frenar y rotar, si choca contra Acelerador ir a 5 unidades de velocidad, y si no choco a 3. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 40 Faltaría un paso más, obtener información de la colisión, ya que con solo saber si colisiono con algo no alcanza, necesitamos saber al menos contra que. Veamos cómo. Se agregó un parámetro más, el que dice “out hit”, entre medio de los anteriores. Este parámetro es un poco diferente a lo que venimos acostumbrados, ya que como vemos, le estamos pasando una variable de tipo “RaycastHit” llamada “hit”, la cual es una variable que posee datos de la colisión. Pero si lo pensamos detenidamente, no tiene sentido pasarle datos de la colisión al rayo, antes de que haya sucedido una, ya que la idea es que el Raycast nos de datos sobre ella, no que se los demos nosotros, y allí es donde entra la palabra “out”. Out se encarga de cambiar el sentido del parámetro, ya que, cuando nosotros le pasamos un dato a la función, es un dato que le damos a ella, un dato que entra a la función (de hecho, en otros lenguajes de programación podemos especificar la palabra “in”). Entonces, Out al revertir el sentido indica que la función va a darnos datos, y los va a poner en la variable “hit” en este caso. Esta es una forma de que una función devuelva más de un dato a la vez. Tener en cuenta que no cualquier parámetro puede ser out, solo los que fueron programados de tal forma, como en Raycast. En este caso creamos una variable de tipo RaycastHit llamada “hit”, pero no le pusimos ningún valor inicial, ya que al pasarse como out, el valor de la variable va a ser completado por el Raycast. Si devuelve true la variable hit va a tener información con de la colisión. Como vemos en la imagen, la propiedad “collider” nos dice contra que Collider choco, y la propiedad “gameObject” del “collider” (recordemos que todo componente tiene una propiedad que indica el objeto en el que está) accedemos al objeto que choco. Claramente al tener acceso al collider o al gameObject podemos hacer GetComponent como hacíamos anteriormente, como, por ejemplo, para acceder al componente Vida y restarle, de esta forma agregando un nuevo tipo de arma al juego. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 41 Ejercicio N°28 Crear un componente que mueva un objeto hacia adelante y dispare un rayo hacia adelante. En caso de que el rayo colisione, destruir al objeto que choco. Recuerden destruir el GameObject y no el Collider (hit.collider), ya que lo último solamente quitaría el componente. Ejercicio N°29 Crear un componente que mueva un objeto hacia adelante y dispare un rayo hacia adelante. En caso de que el rayo colisione, desactivar al objeto que choco usando la instrucción SetActive del GameObject. Ejercicio N°30 Crear un componente que mueva un objeto hacia adelante y dispare un rayo hacia adelante. En caso de que el rayo colisione, acceder al componente Rigidbody del mismo y ejecutar la instrucción AddForce. Tener en cuenta que para que los objetos a los que choca les haga efecto, tienen que estar configurados en “Dinámico Bloqueador Realista”, o sea, sin Infinito en Drag y sin bloquear rotaciones. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 42 Tenemos más datos como el punto exacto de colisión y la distancia, cosa que podríamos usar para reducir el daño según la distancia recorrida, o instanciar un sistema de partículas de chispas en el lugar donde choco la bala, para indicarle al usuario que la bala choca contra algo, ya que, al ser invisible, no tenemos mucha idea de a donde fue la bala. Por ultimo quizás no siempre queremos tener tanto nivel de control y queremos ejecutar versiones más simples. Por ejemplo, tenemos una combinación que no necesita especificar ni distancia ni layers. Y otra que permite especificar solamente el largo. De hecho, hay 16 posibles combinaciones de uso, pero, por ejemplo, no tenemos una que nos dé información de la colisión y nos permita especificar solamente los layers sin especificar el largo. De todas formas, con las vistas hasta ahora es más que suficiente. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning43 Ejercicio N°31 Crear un componente que en el tire un rayo hacia delante y que si choco contra algo instancie un sistema de partículas en el lugar en el que choco. Ejercicio N°32 Crear un componente que tire un rayo hacia delante. Si choco, y la distancia es menor a 5 instanciar un sistema de partículas, y si es mayor otro diferente. Ejercicio N°33 Crear un componente que en el Awake tire un rayo hacia delante y mueva al objeto hacia adelante según la distancia (a mayor distancia, más se mueve). Ejercicio N°34 Crear un componente que en el Awake tire un rayo hacia delante y mueva al objeto hacia adelante según la distancia (a mayor distancia, menos se mueve). Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 44 Rayos desde la cámara Ya sabemos disparar rayos desde un objeto hacia donde está mirando, pero nosotros al estar en un juego en primera persona tenemos que disparar hacia donde la cámara está mirando, ya que la misma seria los ojos del usuario, y el centro de la pantalla es a donde está mirando la cámara. Por ende, podemos sacar por conclusión que, si tiramos un rayo desde la cámara hacia donde está mirando seria disparar un rayo hacia el objeto que está en el centro de la pantalla. Para lograr ello bastaría con simplemente poner un componente en la cámara que tire el rayo usando “transform.position” y “transform.forward”. Si bien ello es completamente valido, a nivel organización no tiene sentido, ya que el arma no está en los ojos, y si tenemos varias armas que usan rayos, no vamos a querer tener muchos componentes en la cámara. Para ello podemos aun dejar el componente de disparo en un objeto que represente el arma, de hecho, en cualquier objeto que queramos. Claramente en ese caso no podemos usar “position” y “forward” ya que no estaríamos tirando el rayo a donde estamos mirando. Para ello podemos usar la propiedad “Camera.main”. Dicha propiedad siempre está conectada a la cámara que tenga el tag “Main Camera”. Recordemos que los tag son similares a los layers, más que nada sirven para agrupar objetos. Si se fijan atentamente, la cámara que viene por defecto en las escenas de Unity tienen dicho tag. Unity se da cuenta de ello y automáticamente conecta esa propiedad a dicha cámara, por lo que a través de ella podemos acceder desde cualquier componente a la cámara principal, y por ende a su posición si necesitásemos. Viendo el arma El arma en un juego de FPS es simplemente un modelo de arma emparentado a la cámara, puesto de forma tal que de la sensación de que está apuntando a donde estamos mirando. Una forma un poco más avanzada de ello es conseguir un modelo de brazos y emparentarle el arma, siempre y cuando los brazos están puestos de una forma tal que parezca que están sosteniendo el arma. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 45 Probablemente se hubiesen imaginado que para lograr esto existía un modelo entero del cuerpo del jugador con el arma. Si bien esto lo han hecho algunos juegos, es una forma muy complicada, ya que lograr que las animaciones se vean bien desde ambas cámaras es complicado. También se preguntarán como es que los otros jugadores ven mi cuerpo entero, mientras que yo no. Eso se debe a que en un juego online (cosa compleja que vamos a cubrir en otro curso entero aparte) cada jugador usualmente tiene dos modelos, el de las manos y el del cuerpo, siendo que el jugador propio ve solo sus manos, y el otro ve solo el cuerpo. Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 46 Bibliografía utilizada y sugerida Recursos Online Videotutoriales de la interfaz de Unity. http://unity3d.com/es/learn/tutorials/topics/interface-essentials Videotutoriales de programación de Unity. http://unity3d.com/es/learn/tutorials/topics/scripting Libros y otros manuscritos Creighton, Ryan Henson. Unity 3D Game Development by Example Beginner's Guide. 1° Edición. UK. Packt Publishing. 2010 Lo que vimos: En esta unidad hemos visto: 1. Cómo utilizar el componente CharacterController para hacer el movimiento de nuestro personaje. 2. Cómo aplicar correctamente emparentamiento a la cámara para hacer una cámara en primera persona, limitando sus rangos de rotación sorteando el problema del “Gimball Lock”. http://unity3d.com/es/learn/tutorials/topics/interface-essentials http://unity3d.com/es/learn/tutorials/topics/scripting Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 47 3. Cómo utilizar Rayos para saber si choco contra un objeto, disparándolos desde la cámara, para así poder crear un arma que dispare proyectiles veloces, ya que no es recomendable instanciar objetos para ello. Lo que viene: Centro de e-Learning SCEU UTN - BA. Medrano 951 2do piso (1179) // Tel. +54 11 4867 7589 / Fax +54 11 4032 0148 www.sceu.frba.utn.edu.ar/e-learning 48 Ahora que ya resolvimos la parte de movimiento, cámara y disparo de nuestro jugador, comenzaremos a concentrarnos en los enemigos. En la siguiente unidad veremos cómo integrar modelos animados humanoides y manipular sus animaciones con los sistemas de Animación de Unity.