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 2: Animaciones Avanzadas 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: Ya que tenemos nuestro personaje en FPS debemos comenzar a concentrarnos en los enemigos. Los enemigos son la tarea más ardua, y que nos va a llevar el resto de las unidades, ya que los mismos poseen IA y animaciones. Aquí comenzamos a ver cómo animar a los enemigos. Con animaciones nos referimos a que se muevan de forma no estática, o sea, que corran moviendo pies y brazos, etc. Esto parecería más de estética que de prototipado, y en parte lo es, pero también necesitamos que el personaje se mueva para poder dispararle en diferentes partes del 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 4 Objetivos: Que los participantes aprendan a: Aplicar y Combinar conceptos de animación para animar a un enemigo. Aplicar y Combinar conceptos vistos anteriormente para hacer daño localizado. 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: Animaciones. Daño Localizado. 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 Animaciones 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 Dándole vida al Personaje Animar un objeto es una tarea del artista 3D. Las animaciones son hechas en el software de modelado 3D. Lo que hacemos desde Unity es importar dichas animaciones, o sea, traerlas a Unity, para poder reproducirlas. En el mundo del modelado 3D existen muchas maneras de animar, de las cuales, Unity soporta huesos (skinning) y morphing, ahora vamos a ver como importar animaciones hechas con huesos. Animando con huesos El modelo 3D aparte de venir con meshes, puede venir con huesos. Ellos no son visibles, son líneas imaginarias con vértices asociados. Cuando los vértices están asociados a un hueso, y él se mueve, los vértices se mueven junto a él, dando la sensación de que se movió el modelo. Asociar vértices con huesos se conoce como “Rigging”. Una vez hecho el “Riggeo” del modelo, se procede al proceso de “Animación”, o sea, a mover los huesos del modelo de una forma que de la sensación de movimiento de personaje. Lo que se hace es poner al modelo en diferentes poses en diferentes momentos, y el sistema automáticamente interpola entre las posiciones, o sea, hace una transición de una a otra constantemente, dando el efecto de animació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 10 Importando modelos con animaciones de huesos Si el modelo viene con animaciones, Unity va a hacer todo lo posible para facilitarnos el trabajo, pero aun así hay que configurar algunos detalles. Cuando seleccionamos un modelo 3D y vemos sus propiedades, vemos 3 solapas, “Model”, “Rig” y “Animations”. En la solapa “Model” vemos configuraciones sobre la importación de Meshes, algunas de ellas las vimos en el curso inicial, “Rig” habla de opciones de importación de huesos y “Animations” nos permite configurar las animaciones que vienen con el modelo. Importando huesos Unity posee 3 formas de importar huesos “Legacy”, “Generic” y “Humanoid”. Legacy se utiliza solamente por compatibilidad con el sistema anterior de animaciones de Unity, por lo que no vamos a utilizarlo. Generic sirve para importar cualquier tipo de sistema de huesos y Humanoid específicamente para sistemas de huesos humanoides. La diferencia entre Generic y Humanoid es que el sistema de animación posee muchas características exclusivamente pensadas para figuras humanoides, que no se pueden aplicar a modelos de otra estructura, como Caballos o cualquier tipo de cuadrúpedos, Pulpos, Arañas, en resumen, cualquier figura no humanoide. 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 Por ahora trabajaremos con Humanoides, pero si quieren importar un modelo 3D que no sea humanoide es perfectamente posible. Otro detalle es que cuando bajen un modelo 3D del Asset Store o de un archivo descargado de internet, y es humanoide, recordar siempre verificar la propiedad “Animation Type” para asegurarse de que esté en modo humanoide,porque puede que Unity no lo reconozca automáticamente y tengan que cambiarlo. Luego tenemos la propiedad “Avatar Definition”, que está independientemente del tipo de huesos que elegimos. Esta sirve para especificar como se crea el Avatar. El Avatar es un objeto que contiene la configuración de los huesos, y que se crea automáticamente cuando importamos un modelo. Este objeto anteriormente no existía, por lo que la configuración de huesos se guardaba en el mesh, pero ahora se separó en un objeto aparte para poder compartir esa configuración con otros modelos. Esto se debe a que a pesar de que Unity reconoce el esqueleto automáticamente la mayoría de las veces, puede fallar, y también en el modo Humanoide uno puede ajustar muchos detalles, por lo que si tenemos muchos modelos similares que queremos que tengan todos la misma configuración particular, basta que con configurar uno solo y usar esa configuración con varios (ej. selección de diferentes personajes que se tienen que mover igual, un sistema de generación de multitudes, donde hay muchos modelos de personas que comparten animaciones). En el caso de que queramos que nuestro modelo tenga su propia configuración seleccionamos “Create From This Model”, haciendo que nuestro modelo no tome la configuración de otro. Si seleccionamos “Copy From Other Avatar” se nos habilita una propiedad “Source” que podemos conectarla a un avatar de otro modelo. Por ahora no vamos a hacer modificaciones a la configuración automática del avatar, por lo que con poner “Create From This Model” en todos los modelos alcanza. Más tarde usaremos el avatar en un componente. Configurando el avatar Si bien la mayoría de las veces no vamos a tener que hacer esto, si importamos un modelo, la configuración automática de huesos para Humanoides puede fallar, por lo que 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 vamos a necesitar modificarla. Para darnos cuenta si falló o no tenemos que fijarnos si hay lo que aparece a la izquierda del botón “Configure”. Si aparece “…” (tres puntos suspensivos) significa que hace falta aplicar los cambios, ya que hasta que no pase eso Unity no va a intentar leer los huesos, entonces simplemente hay que hacer clic en el botón Apply debajo de todo. Si aparece una tilde significa que la importación fue exitosa y no hay que hacer nada, a menos que queramos ajustar detalles. Y, por último, si aparece una cruz significa que algo falló. Esto suele suceder cuando el esqueleto no respeta los lineamientos a seguir a la hora de animar, como que el personaje este en la pose “T”, o que los huesos estén mal emparentados entre sí (más sobre esto adelante) desde el modelo 3D. Tanto en caso que queramos modificar detalles o falle la importación debemos hacer clic en el botón “Configure”, el cual dependiendo de la versión de Unity irá al modo de edición, o seleccionará el asset del Avatar correspondiente, donde luego podremos hacer clic en el botón Configure Avatar. En el modo de edición de avatar se carga una escena donde podremos ver el modelo y su jerarquía de huesos en el panel de Hierarchy. Como vemos, los huesos no son más que objetos vacíos los cuales están emparentados entre sí, o sea, que, si movemos un hueso como el del brazo, que tiene como hijo el antebrazo y en la mano, se mueve todo junto. De todas formas, generalmente no vamos a mover nunca el hueso nosotros, de eso se encargará la animación más adelante. Luego podemos ver en el panel de inspector una figura que muestra el esqueleto, la cual muestra en verde las partes que están correctamente configuradas, y en rojo las que no. Si el sistema de importación fue exitoso deberíamos ver todo verde, pero sino veremos rojo en las partes donde hubo un problema. Para darnos cuenta cual fue el problema podremos observar los círculos que están repartidos por todo el hueso. Los círculos que tienen la línea 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 punteada son huesos opcionales, o sea que si no están configurados no hay problema, ya que Unity puede compensarlos automáticamente, pero los que no están punteados y no están configurados produce error. Para saber si el hueso está configurado vemos adentro del circulo un punto verde, pero si está vacío significa que no está configurado. Por ejemplo, en la imagen a nuestra derecha no están asociados huesos al codo derecho y la rodilla izquierda. Para poder asociar los huesos podremos ver debajo del dibujo una lista de propiedades con el nombre del hueso, las cuales podremos conectar arrastrando el hueso deseado a la propiedad. Si nosotros hicimos los huesos en el modelo 3D vamos a saber cuál va en qué lugar, pero sino generalmente los huesos tienen un nombre que nos ayuda a saber cuál va en qué lugar. Lamentablemente hay veces que no se puede salvar la situación, ya que el modelo viene mal hecho, por lo que habrá que modificarlo, pero esto depende de los huesos en sí. Si no se puede hacer este proceso a mano, se puede intentar hacer un procedimiento manual que quizás ayude. En el botón que dice Pose se puede hacer clic en el botón “Sample Bind-Pose”, luego en el botón Mapping donde dice “Automap” y luego de vuelta en Pose donde dice “Enforce T-pose”. No hay garantías de que esto ayude, pero queda como último recurso antes de darse por vencido con el modelo. 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 Una vez hechos los cambios se puede hacer clic en el botón Apply y finalmente Done. Si nos arrepentimos de los cambios podemos hacer clic en el botón Revert. Importando animaciones Una vez configurados los huesos, nos falta configurar las animaciones. La configuración de las animaciones es independiente de las de los huesos, por lo que podemos configurarlas en cualquier orden y cambiarlas cuando queramos. Primero hay que asegurarse de que esté tildada la propiedad “Import Animation”, para asegurarnos de que Unity vaya a importarlas, ya que hay casos en las cuales no nos interesan las animaciones de un modelo, y así ahorramos tener animaciones extras. Una de las cosas más importantes que vamos a configurar aquí son lo que se conoce como “Animation Clips”. Cuando uno hace una animación en un software 3d, estas se hacen sobre lo que se conoce como Línea de Tiempo, sobre la cual uno va poniendo diferentes poses en diferentes partes de la línea para hacer la animación. Sobre esta línea se ponen todas las diferentes animaciones del modelo, pero dependiendo de la situación vamos a querer reproducir diferentes porciones de la misma, dichas porciones serían los Clips. Nuestro trabajo aquí es cortar la línea de tiempos en partes, ya que Unity la importa entera. 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 Para crear una porción simplemente hacemos clic en el botón “+” del recuadro Clips. Luego seleccionamos el clip que creamos y le cambiamos el nombre del clip a un nombre adecuado usando el cuadro de texto que se encuentra debajo del recuadro Clips. Luego podremos especificar el inicio y el fin de dos formas, una es modificando las propiedades Start y End, especificando manualmente cual frame de la animación es el comienzo, y cual el fin, información la cual debería haber sido proveída por el modelado. La otra opción es mover las flechas azules en la barra de tiempo para ubicarlas a ojo. De una forma u otra, podremos ver el resultado haciendo clic enel botón de Play que se encuentra debajo para ver si la porción es la deseada, y también ver que, en el caso de que la animación deba repetirse (loop), el principio y el fin coincidan. En caso de que no queremos que la animación sea un Loop, simplemente destildamos la opción Loop Time debajo de las propiedades Start y End. Separando los modelos, huesos y animaciones Unity viene con modelos 3D animados en el paquete que podemos incluir yendo a “Assets -> Import Package -> Characters”. El archivo que tiene el modelo se llama “Ethan.fbx”. Si buscamos ese modelo, vemos que viene con el modelo en sí, los huesos, pero no tiene animaciones. Ustedes se preguntarán porqué existiría un modelo con el Rigging hecho, pero sin animaciones. Si seguimos viendo hay otro FBX que tienen el caso contrario, no tienen modelos, pero si huesos y animaciones. No hay que confundirse de modelo cuando 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 vemos las animaciones, ya que, si el modelo no tiene el mesh, Unity muestra un modelo 3D de muestra, que es el que está en la imagen arriba. Si vemos lo que tienen en común estos archivos que tienen modelo-huesos, y huesos- animación, salta a la vista que ambos tienen huesos. Esto hace que si los huesos de un archivo “modelo-huesos” son compatibles con los de un “huesos-animación”, se puedan usar las animaciones de un archivo, con el modelo de otro. Esta separación se debe a que muchas veces tenemos modelos diferentes, con el mismo sistema de huesos, y deseamos que todos tengan la misma animación. Por ejemplo, tenemos un juego donde el jugador puede seleccionar varios personajes, pero que cuando jugamos con ellos tienen los mismos movimientos (por ej.: Batman Arkham City). En este juego, habría un archivo por cada personaje, y un archivo por cada animación, y luego se pueden aplicar las animaciones de los archivos en animación en cualquier personaje deseado. Ejercicio N°1 Conseguir un modelo humanoide del Asset Store o usar a Ethan, que está en “Assets -> Import Package -> Characters”. Configurar los huesos en modo humanoide en caso de que no lo esté. Asegurarse de que la configuración automática este bien, en caso contrario, ver si se puede arreglar. Si no, buscar otro modelo. Configurar las animaciones de los archivos de animación (si es que no están en el propio modelo), en caso de que ya venga con animaciones, borrarlas seleccionándolas y haciendo clic en el botón “-“, así pudiendo volver a recrearlas. 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 17 Ejercicio N°2 Conseguir un modelo humanoide del Asset Store o usar a Ethan, que está en “Assets -> Import Package -> Characters”. Configurar los huesos en modo Generic en caso de que no lo esté. Configurar las animaciones de los archivos de animación (si es que no están en el propio modelo), en caso de que ya venga con animaciones, borrarlas seleccionándolas y haciendo clic en el botón “-“, así pudiendo volver a recrearlas. Animando un objeto Una vez configurado correctamente el modelo, ya estamos en posición de comenzar a aplicarlo. A la hora de usar un modelo animado, conviene crearlo arrastrando el modelo a la escena directamente. Recordemos que un modelo 3D puede venir con más de un mesh, que emparentados de la manera adecuada forman a un modelo entero, y a esto hay que sumarle los huesos. Al ser tan compleja la estructura de un modelo animado con huesos, conviene crearla a partir del modelo en vez de ir cambiándola de poco a mano. También hay una diferencia con respecto a lo que veníamos haciendo. Los modelos estáticos usaban los componentes MeshFilter y MeshRenderer, y con cambiar el mesh del MeshFilter alcanzaba. Para modelos animados se usa otro componente, el “SkinnedMeshRenderer”, el cual posee una serie de propiedades que hay que configurar correctamente, cosa que Unity hace automáticamente por nosotros si creamos el objeto a partir del modelo. 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 El objeto padre de todos (en el caso de la foto seria “Ethan”) es un objeto vacío que tiene emparentado los meshes del modelo y el sistema de huesos. Podemos seleccionar algún hueso del sistema, rotarlo y ver como se mueve el modelo. También podemos apreciar como un hueso es un objeto vacío, y puede tener emparentado otros objetos. Si bien se pueden mover los huesos de esta forma, la idea es que los huesos se muevan automáticamente con las animaciones que importamos, y de ello se encarga el componente “Animator” que está en el padre. Este componente se encarga de aplicar las animaciones que tiene el modelo. Como vemos tiene una propiedad Avatar, la cual ya viene configurada con el Avatar que tiene la configuración de los huesos. Root Motion 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 Una propiedad que por ahora no vamos a estar utilizando es “Apply Root Motion”. Esta propiedad mueve el modelo en base a la animación, por lo que el movimiento de objeto es gobernado por la animación. Nosotros vamos a estar utilizando otra forma para mover a los enemigos, por lo que vamos a querer que esté destildado así no pelea el movimiento de la animación con el del sistema de IA que vamos a utilizar. Generalmente esta propiedad está pensada para el personaje del jugador, o para ciertas situaciones donde necesitamos que el movimiento se sincronice con la animación, como escalar una pared. Animator Controller La propiedad más importante ahora es “Controller”. Esta propiedad dice que animaciones puede reproducir el modelo. Un controller es otro asset, o sea, un archivo, el cual posee las animaciones que puede reproducir el modelo, y una lógica de transición de animaciones. Al igual que antes, las animaciones que tiene un modelo y su lógica de transición, al estar en un archivo separado permite reutilizar esta lógica en varios modelos, por lo que, si conectamos un Controller a varios objetos, todos esos objetos van a tener las animaciones que dicen el Controller, y si cambiamos la configuración del Controller para que tenga otra lógica, dicho cambio se les aplica a todos los objetos. Para crear un controller, al igual que cualquier asset, vamos al botón Create del panel de Hierarchy, y allí seleccionamos la opción Animator Controller. Una vez creado el Controller podemos asociarlo a nuestro objeto arrastrándolo a la propiedad Controller del objeto a animar, o haciendo clic en el círculo a la derecha de dicha propiedad, y buscarlo en el selector de Controllers. Una vez vinculado el controller con el objeto, podremos pasar a editar el Controller, para así agregar las animaciones y la lógica de transición. Para ello simplemente hacemos doble clic en el asset y se abrirá su editor, la ventana Animator. Apenas abrimos la ventana vemos muchas cosas, iremos de a poco viendo que significa cada una. Lo primero que debemos hacer es agregarle las animaciones que deseamos 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 que nuestro controller maneje, o sea, que tengan los objetos que estén asociados al controller. Para ello simplemente buscamos los clips de animacióndentro de los modelos 3D y los arrastramos a la ventana de controller. Tener en cuenta que hay que tener seleccionado el controller correspondiente, sino quizás estemos agregando a la animación a otro controller. A medida que vamos agregando animaciones se van agregando rectángulos grises, indicando que los mismos están en el controller. También vemos que el primero que agregamos aparece de color naranja, indicando que esta animación va a ser la que viene por defecto, o sea, la primera que se reproduce sola. Si queremos cambiar la animación que, por defecto, hacemos clic derecho sobre la que deseamos que sea la por defecto y hacemos clic en “Set as Layer Default State”. Por ejemplo, si estamos animando un personaje que camine, seguro va a haber una animación de estar parado (normalmente conocida como “Idle”), y esa probablemente sea la que deseemos que esté por defecto, ya que luego nosotros podremos hacer que cambie. Cambiando de animación Si deseásemos hacer un personaje humanoide, probablemente vayamos a tener animaciones como estar parado (Idle), caminar o correr, saltar, etc. Dichas animaciones tienen que cambiarse en momentos determinados, como cuando el usuario presiona la tecla de correr y cuando la suelta, entre otros. Si bien hay varias formas de hacer estas transiciones, primero veamos la más simple, aunque menos poderosa, la cual consta de decirle por código al animador que deseamos que se reproduzca una animación específica. 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 El componente del ejemplo está en el objeto del modelo que tiene el componente Animator. Lo que hicimos fue arrastrar el componente a la propiedad animator, para así indicar que la propiedad está conectada al mismo. Luego, ejecutamos la instrucción Play cuando presionamos la tecla arriba, indicándole que queremos que reproduzca la animación “Run”, y cuando la soltamos, que vaya a “Idle”. Si creamos un modelo animador a partir del modelo 3D, creamos el controller y agregamos las animaciones Run e Idle (pueden llamarse diferente), configuramos el controller del objeto animado para que se conecte al que creamos, y finalmente ponemos este componente y conectamos su propiedad animator al animator del objeto animado, vamos a tener un objeto que cambia de animación cuando presionamos la tecla arriba. 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 Ejercicio N°3 Crear un Animator Controller y arrastrarle dentro algunas animaciones del modelo que conseguimos en los ejercicios anteriores. Crear un componente que cuando se presione una tecla reproduzca alguna de esas animaciones con la instrucción Play, y luego cuando se suelte otra. Agregar el controller al Animator del objeto del modelo animador que conseguimos, y también el componente que hicimos. Asegurarse de arrastrar el Animator a la propiedad de nuestro componente. Ejercicio N°4 Crear un componente que cuando se presione una tecla reproduzca alguna de esas animaciones con la instrucción Play. Hacer por lo menos que el componente detecte 3 teclas y cambie a 3 animaciones. Ejercicio N°5 Crear un componente que cuando detecte un OnTriggerEnter reproduzca una animación, y en el OnTriggerExit otra. Configurar el objeto en modo Trigger. 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 Transiciones Hay dos temas a tener en cuenta. Uno es que las animaciones cambian abruptamente, sin ningún suavizado, dando un resultado tosco. Luego la lógica de animación está mezclada con el código, y si un artista desea cambiar cómo se comporta la animación debe cambiar el código, cosa que no es deseable. Para el suavizado existe la función CrossFade, pero es difícil de manejar. Para resolver ambos problemas existen las Transiciones. Permiten diagramar las posibles transiciones entre estados desde el Controller, siendo esta una de sus principales características. La idea detrás de ello es que el artista controle que animación le sigue a cuál. Aparte de facilitarle el trabajo al animador, también poseen suavizado, resolviendo el problema. En este controller, existe la animación de parado (Idle), caminando (Walk), correr (Run), agachado (Crouch) y saltando (Jump). Vemos como en este caso hay transiciones de ida y vuelta en todas, siendo estas las líneas blancas con las flechas. Dichas transiciones se pueden crear haciendo clic derecho sobre la animación desde la cual se hace la transición y seleccionando “Make Transicion”, para luego hacer clic en la animación a la cual queremos ir. Condiciones y Parámetros Booleanos En este caso se puede ir de todas las animaciones a todas las animaciones, cosa que podíamos hacer tranquilamente por código, pero la gracia de este sistema reside en las condiciones asociadas a las transiciones. Las condiciones, al igual que con los ifs, son situaciones que se tienen que dar para que la transición sea posible. Si yo estoy en el estado Idle, para ir a Jump se tiene que dar la condición de que la tecla de salto esté presionada, para Crouch la de agacharse y para Walk la de caminar. 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 Ahora, para ir de Walk a Run tengo que presionar, aparte de la de caminar, la de correr (algo normal en los video juegos) y para volver a Walk tiene que soltarse la de correr. También si estoy en Walk o Run con presionar la tecla de salto también debería ir a Jump, pero, por ejemplo, si suelto la tecla de saltar, vemos que puede ir a Idle, Walk y Run. En ese caso, la condición para ir de Jump a Idle sería que la tecla de salto no esté presionada y que tampoco esté la de caminar, la de ir de Jump a Walk es que no esté presionada la de salto, pero si la de caminar, y la condición para ir de Jump a Run es que estén ambas. Como vemos cada transición debe responder a la situación que necesitamos. Vale la pena destacar que, si estoy en un estado y se cumple una condición de una transición de otro estado, no pasa nada, las únicas transiciones que se chequean son las del estado (animación) en el que estoy actualmente, ya que no es posible estar en dos estados en simultaneo, solo en uno. Ahora como vemos, el diagrama de transiciones que acabe de describir se basa en si está o no presionada cierta tecla. Para que esto sea posible necesitamos indicarle a nuestro controller cada una de las posibles variables que van a intervenir en las condiciones, siendo en este caso 4 booleanos, uno para la tecla de caminar, una para la de correr, otra para la de agacharse, y finalmente la de saltar. Estos parámetros los vamos a poder utilizar en las transiciones, y luego modificaremos su valor mediante código. Para crear un parámetro, hay que hacer clic en la solapa Parameters arriba a la derecha y luego en el botón “+”, donde seleccionaremos en este caso “Bool” y luego ingresando el nombre del parámetro. En este caso repetiremos este proceso 3 más para tener 4 booleanos que representen las teclas. Pueden cambiar el nombre del parámetro haciendo doble clic sobre él. Ahora que ya tenemos los parámetros para nuestras transiciones, para agregar una condición a una transición, hay que seleccionar la transición,y en el recuadro de Conditions hacer clic en el botón “+”. Veremos que ahora aparece un recuadro de selección donde podremos ver los parámetros que elegimos. Si seleccionamos una opción booleana, como las que creamos, a la derecha aparecerá otro cuadro de selecció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 25 donde nos ofrece las opciones “True” y “False”. Por ejemplo, para la transición de Idle a Walk, pondríamos en el recuadro de la izquierda “Caminar”, y en el de la derecha “True”, indicando que la transición se cumple si dicha variable pasa al estado True. Veamos las transiciones de Parado, Caminar y Correr. Veamos claramente que podemos poner dos condiciones, y estas actúan como su fuese un AND (&&) en programación. Si quisiésemos hace un OR (||) podemos agregar más de una transición a las mismas animaciones. Si ahora damos play al proyecto, veremos al objeto ejecutando la animación que viene por defecto (la naranja). Si mantenemos la ventana Animator abierta, seleccionamos el objeto que está moviéndose, y tildamos “Caminar” desde el editor, veremos como sucede la transición. De esta forma podemos probar la transición entre estados. 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 También si seleccionamos el objeto mientras el juego está corriendo y abrimos la ventana Animator (Window -> Animator) podremos ver que animación se está reproduciendo. Ella sería la animación que tiene una barra azul en movimiento, indicando en que momento de la animación se encuentra. También desde aquí, como dijimos anteriormente, podremos cambiar los valores de los parámetros y visualizar las transiciones. 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 Ejercicio N°6 Crear un controller con dos animaciones y un parámetro booleano. Hacer una transición entre ambas animaciones, que suceda cuando el booleano esté en true. Probar la animación cambiando el booleano. Ejercicio N°7 Crear un controller con dos animaciones y un parámetro booleano. Hacer dos transiciones entre ambas animaciones, una que suceda cuando el booleano esté en true, y la otra cuando esté en false. Probar la animación cambiando el booleano. Ejercicio N°8 Crear un controller con tres animaciones y dos parámetros booleanos. Hacer la transición de la primer a la segunda animación cuando el primer booleano se encienda, y de la segunda a la tercera con el segundo. Probar la animación cambiando el booleano. 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 Cambiando los parámetros por código Ahora que ya comprobamos que las transiciones funcionan correctamente, quedaría combinar el código de movimiento con el sistema de animación. Para ello tendremos que usar una serie de funciones del componente Animator. Al igual que antes, haremos un componente que tenga una referencia al animator, lo conectamos por editor, pero esta vez hacemos uso de la función SetBool. El código es similar al anterior, pero la diferencia radica en que ahora nosotros solamente informamos si estamos caminando o no, y lo que sucede con la animación pasa al control del animador para que pueda hacer lo que quiera, y así poder trabajar en equipo correctamente. 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°9 Crear un componente que encienda y apague un booleano del controller cuando se presiona y suelta una tecla, al igual que el código de ejemplo. Ejercicio N°10 Agregar a un personaje humanoide el código de movimiento con gravedad y salto hechos en la unidad anterior. Crear un controller con una animación de estar parado (Idle) y otra de estar saltando (Jump), y que haya transición de ida y vuelta entre ambas. Dichas transiciones deben depender de un booleano llamado “Grounded” (traducción de tocando el piso). Encender el booleano cuando estamos tocando el suelo, y cuando no soltarlo. Ejercicio N°11 Hacer un humanoide con un controlador que tenga dos animaciones, y las transiciones de ida y vuelta. La de ida debe depender de un booleano, pero la de vuelta no debe poseer ninguna condición. Crear un componente para probar las transiciones. 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 Configuraciones Avanzadas de una Transicion Veamos que significa cada propiedad de la transición. Has Exit Time: Esta es una condición más a tener en cuenta. Si esta tildada actúa como condición de que, para ejecutarse la transición, la animación debe primero llegar el tiempo de fin. Por ejemplo, si hacemos una transición del estado A al B que no tiene condiciones, pero tiene tildada esta opción, va a pasar que cuando se llega al estado A, y el estado A termine, automáticamente se pasa al estado B. Esto es útil para cuando queremos hacer animaciones de paso entre dos animaciones. Por ejemplo, si estamos corriendo para adelante y queremos parar, pero no queremos que sea brusco, sino que haya una animación de desacelerar, podemos poner una animación de desaceleración entre medio de las de correr y estar parado, y hacer que cuando termine la de transición, vaya automáticamente a la de estar parado. Hay que tener en cuenta que viene tildado por defecto, y si no lo destildamos, por más que se cumpla las condiciones que configuramos anteriormente, también espera a que termine la transición, por lo que generalmente vamos a querer destildarla. Exit Time: Valor entre 0 y 1 especificando en que porcentaje de la animación se considera que termina. Esta va en conjunto con Has Exit Time. Fixed Duration: A la hora de especificar cuánto dura la animación, determina si se mide en segundos (tildada) o en porcentajes (destildada). Transition Duration: Cuanto dura la transición. Transition Offset: Especifica en que momento de la otra animación arranca la transició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 31 Ejercicio N°12 Hacer un controller que tenga tres animaciones y un bool. Una transición debe conectar la primera animación con la segunda cuando se presione una tecla, y otra debe conectar la segunda animación con la tercera, pero sin condiciones debe hacer que cuando termine la segunda animación vaya a la tercer utilizando Has Exit Time. Tener en cuenta que la segunda animación no debe loopear (destildar Loop Time en las opciones de importación), si no esto no funcionará correctamente Ejercicio N°13 Hacer un controller similar al anterior, pero que la animación no solo pase de la primera a la tercera sino también de la tercera a la primera, pasando también por la segunda animación, y de igual forma que antes, que la segunda vaya a la primera con una transición con Exit Time. Ejercicio N°14 Hacer un controller similar al anterior, pero esta vez cuando se vuelve de la tercera animación a la primera, debe pasar por una cuarta animació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 32 Propiedades numéricas Como vimos cuando creamos parámetros había más opciones que Bool, de hecho, había 4. Veamos el tipo de datos Float. Al igual que en programación, representa números con decimales, y al igual que el bool, se pueden usar en transiciones como cualquier otro parámetro. Si creamos una transición con una condición que use ese tipo vemos que las opciones no son más “True” o “False”, sino “Greater” (mayor que) o “Less” (menor que), y también se nos agrega un recuadro con un número. La idea es hacer condiciones como hicimos anteriormente pero más reducido, podemos preguntar si un número es mayor o menor que otro. Por ejemplo, podemos recrear el caso de correr y caminar utilizando una propiedad llamada “Velocidad”, la cual puede obtener el valor del movimiento que le dimos ese frame al objeto. Entonces, las condiciones para estar parado, caminar y correr pueden depender de esa velocidad. Para ir de Idle a Walk podemos poner que la velocidad tenga que ser mayor a 0, de Walk a Run que sea mayor a 0.5, ya que sería conveniente manejar la velocidad en porcentajes, y luego de Run a Walk tiene que ser menor a 0.5, y de Walk a Idle menor a 0.1, ya que no podemos poner menor o igual a 0 acá. Y también, al igual que las booleanas, podemos cambiarlas desde el editor cuando el juego se está reproduciendo para probarlas. 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 Ejercicio N°15 Hacer un controller que cambie de una primera animación a una segunda si un parámetro de tipo float del controller es mayor que 0.5. Ejercicio N°16 Hacer un controller similar al anterior, pero agregarle que de la segunda animación vuelva a la primera cuando el float sea menor que 0.5. Ejercicio N°17 Hacer un controller como el del ejemplo del manual. Tiene que tener Idle, Walk y Run y debe ir y volver en base a la velocidad. 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 Blend Trees Hay una tercera forma de animar a la caminata de un personaje, que es usando Blend Trees. Un Blend Tree se ve en el controller como una sola animación, por lo que puede tener transiciones a otras animaciones u otros Blend Trees, pero adentro tiene muchas animaciones. La idea es que ellos son estados del animador en los cuales se mezclan varias animaciones en base a parámetros. En su modo más simple, uno puede especificar un float, y en base a que vale ese float mezcla las animaciones. Para crear uno, hacemos clic derecho en cualquier parte vacía del controller y hacemos clic en donde dice “Create State -> From New Blend Tree”. Vemos que efectivamente se ve como si fuese una animación, pero cuando le hacemos doble clic entramos a editarlos. Vemos en el lado del gráfico una barra que en este caso dice velocidad. También si nos fijamos a la derecha, en el panel del Inspector, vemos la propiedad Parameter que dice velocidad. En este caso se puso automáticamente porque es el primero parámetro de tipo Float que tengo en este controller. También vemos que hay un recuadro que dice motion, donde podemos hacer clic en el botón “+” y seleccionar “Add Motion Field”, siendo esta la forma de agregar animaciones a nuestro blend tree. Una vez agregado tenemos que especificarle que animación buscándola con el circulo o arrastrándosela. 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 A medida que agreguemos animaciones al blend tree, veremos un gráfico arriba, mostrando como las animaciones se van a mezclar dependiendo del valor del parámetro, en este caso Velocidad. Vemos como la columna Threshold muestra en qué valor del parámetro se va a ubicar la animación. En este caso Idle esta en 0, o sea, cuando Velocidad vale 0, Walk en 0.5 y Run en 1. Si Velocidad va alguno de esos valores se va a ejecutar la animación correspondiente, pero la gracia del sistema sucede cuando está en valores intermedios. Por ejemplo, si Velocidad valdría 0.25, se encontraría en la mitad exacta entre Idle y Walk, en este caso, mezclando las animaciones un 50% 50%. La idea es que velocidad suba progresivamente a la velocidad a la que se está moviendo el jugador, para así hacer una transición suave. Recordemos que hay juegos en los cuales controlamos la velocidad con la palanca, y dependiendo de cuanto presionemos la palanca, cuanto se mueve el jugador, este sería una forma de poder ajustar la animación con respecto al movimiento para que concuerden. Otro detalle es que los Thresholds se ajustan automáticamente a valores entre 0 y 1, pero si queremos cambiarlo, podemos destildar la opción Automate Thresholds e ingresar los valores que queramos. Luego la columna con el reloj es para poder afectar la velocidad de reproducción de la animación por si queremos que sea más rápida o más lenta, y la tilde de la figura humana sirve para hacer mirror, o sea, espejar la animación. Todas estas propiedades sirven para mezclar animaciones y hacer que concuerden en caso de que no lo hagan. Finalmente, podemos probar todo esto desde el editor. 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 Ejercicio N°18 Hacer un controller que tenga solamente un blend tree. El blend tree debe tener dos animaciones Idle y Run, y deben interpolarse en base a un parámetro float. Ejercicio N°19 Hacer un controller similar al anterior pero que tenga Idle, Walk y Run. Ejercicio N°20 Hacer un controller similar al anterior pero que tenga Reverse (caminar hacia atrás), Idle, Walk y Run 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 Blend Trees 2D Si deseamos, podemos agregar un parámetro más a nuestro Blend Tree y convertirlo en 2D. Anteriormente nuestras animaciones estaban ubicadas en una línea, donde su posición solo se podía mover en el eje X, en modo 2D, las animaciones tienen dos ejes, o sea, se pueden ubicar en un gráfico 2D, y dependiendo de qué tan cerca este con respecto a los dos parámetros, el porcentaje de animación a reproducir. Por ejemplo, si tuviésemos animaciones de doblar a la izquierda y la derecha, podríamos tener un Blend Tree con las propiedades VelocidadMovimientoy VelocidadRotacion, y las animaciones, Parado, ParadoRotarIzquierda, ParadoRotarDerecha, Caminar, CaminarIzquierda, CaminarDerecha, Correr, CorrerIzquierda y CorrerDerecha. Dichas animaciones estarían dispuestas de una forma tal en la cual se ejecuten en el momento necesario según las propiedades VelocidadMovimiento y VelocidadRotacion. Para poner el Blend Tree en modo 2D, cambiamos la propiedad “Blend Type” a “2D Freeform Cartesian”. Hay otros modos, pero en el manual nos vamos a concentrar en este. En este caso pusimos como primer parámetro la velocidad de rotación, así representa el eje X, y luego la velocidad de movimiento representando el eje Y. Luego vemos como ubicamos cada animación en su lugar correspondiente. En este caso pusimos animaciones en X yendo de -1 a 1, y en Y de 0 a 1 (no contamos marcha atrás). También vemos un punto rojo, el mismo representando los valores actuales de los dos parámetros, los cuales podemos probar cambiando las barras del gráfico. 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 Ejercicio N°21 Hacer un controller que tenga un blend tree 2d con las animaciones Idle, Run y RunLeft y RunRight. Ejercicio N°22 Hacer un controller que tenga un blend tree 2d con las animaciones Idle, Walk, WalkLeft, WalkRight, Run, RunLeft y RunRight. Ejercicio N°23 Hacer un controller que tenga un blend tree 2d con las animaciones Idle, IdleLeft, IdleRight, Walk, WalkLeft, WalkRight, Run, RunLeft y RunRight. 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 Combinando Blend Trees Con un Blend Tree pudimos hacer todas las posibles animaciones del personaje cuando está parado, o sea, estar parado, caminar, correr y sus combinaciones para izquierda y derecha. ¿Pero qué pasa si queremos hacer las mismas animaciones para cuando está agachado? Lo más lógico sería hacer una especie de Blend Tree 3D, donde el tercer eje represente si el jugador está parado o agachado, pero esto no es posible. Lo que sí se puede hacer es hacer un Blend Tree 1D, que tenga dos Blend Trees hijos 2D. Para hacer ello simplemente a la hora de agregar una animación a un Blend Tree, en vez de seleccionar “Add Motion Field”, seleccionan “New Blend Tree”, y van a ver en el gráfico que muestra como hijo del Blend Tree principal otro Blend Tree hijo. Para el caso particular de estar agachado y saltar, probablemente esta no sería la mejor opción, ya que no podemos estar a medio camino entre estar parado y agachado, o estamos parado o agachados, cuanto mucho vamos a querer que haya una transición entre los dos estados, pero esto lo podemos lograr con transiciones regulares entre Blend Trees, cosa que es perfectamente posible. 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 Configurando parámetros Float Al igual que con los parámetros Bool, tenemos que pasar esos valores desde programación. Para ello podemos hacer uso de la función SetFloat del Animator. En este caso creamos una variable local (recordemos que son temporales) de tipo float y le ponemos el valor en 0. Si presionamos la tecla arriba, preguntamos si está presionado el Shift (tecla común para correr), en tal caso ponemos la velocidad en 1, sino en 0,6. Fijémonos que, si no presionamos ninguna tecla, la variable velocidad queda con su valor original, o sea, 0, por lo que no hace falta cambiarlo. Una vez calculada la velocidad se la pasamos al animator y luego la podemos usar para, por ejemplo, mover con transform.Translate o la función Move del CharacterController. De todas formas, nosotros vamos a estar usando este sistema para el enemigo, entonces no nos tenemos que preocupar por esas cosas ya que lo vamos a estar moviendo de otra forma. 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°24 Hacer un componente que controle un blend tree 1D, cambiando el parámetro float con el eje Vertical del Input. Ejercicio N°25 Hacer un componente que controle un blend tree 2D, cambiando los parámetros float con los ejes Vertical y Horizontal del Input. Ejercicio N°26 Hacer un componente que controle un blend tree 2D, cambiando un parámetro float con el eje Vertical y otro con una propiedad float del componente configurable por el editor. 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 Suavizando parámetros Float Hay un problema al hacer lo que hicimos antes, especialmente con los Blend Trees. Los Blend Trees automáticamente se ubican en el valor que nosotros le pongamos a los parámetros, pero anteriormente hicimos el cambio brusco entre 0, 0.6 y 1. De esta forma los blend trees no liberan su potencial, que es poder ponernos entre medio. Una forma de solucionar esto es utilizando ejes en vez de teclas, situación en la cual el código quedaría de la siguiente forma. En este caso, aprovechamos que GetAxis nos da valores entre -1 y 1 indicando cuanto el usuario se quiere mover. Esto permite que el usuario apreté la palanca lo que desee y así especifica cuanto se quiere mover, haciendo que el sistema de animación se ajuste. Ahora, si bien esto corrige ligeramente el problema hay otro detalle, el personaje del juego generalmente tarda en llegar a la velocidad deseada. Si nosotros estamos quietos, y apretamos rápidamente la palanca para arriba estamos indicando al personaje que queremos ir a máxima velocidad y el empieza a correr para llegar a esa velocidad, lo mismo para cuando soltamos la palanca, no frena instantáneamente, si no que frena de a poco. El problema del código de arriba es que no contempla ello, entonces el valor en el que está la palanca es automáticamente pasado como la velocidad actual, haciendo que sea muy tosco el movimiento. Para solucionar esto usaremos la función Mathf.Lerp. 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 43 Analicemos el código. Primero tenemos la variable local “velocidadDeseada” que guarda el valor que indica la velocidad que el usuario desea al presionar el eje. En este caso dicha variable es local, ya que los deseos cambian todo el tiempo por lo que no necesitamos guardarla. Luego tenemos una propiedad velocidadActual, la cual es propiedad ya que necesitamos guardarla para mantener la velocidad real del jugador. El valor de dicha propiedad lo vamos cambiando por el resultado de la función Mathf.Lerp, una función encargada de interpolar valores. El primero parámetro es el valor que queremos hacer que se vaya acercando a otro, el segundo parámetro es el valor destino al cual queremos llegar, y el tercer parámetro es la velocidad que queremos que tarde en llegar, para finalmente retornar el valor más cerca del destino. Al ejecutar esta función todos los frames, vamosa hacer que la velocidadActual vaya acercándose a la velocidadDeseada, por lo que por más que la velocidad deseada cambie constantemente, la velocidad actual, la que gobierna nuestro movimiento, va a ir cambiando progresivamente, sin pegar saltos bruscos. El tema con esta función es que se va a mover con una velocidad decreciente, o sea, va a ir primero rápido y a medida que se acerca va a ir decrementando su velocidad. Si nosotros queremos que vaya siempre a la misma velocidad hacia el destino tenemos la función Mathf.MoveTowards, que funciona igual pero que va a un ritmo constante. 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 Ejercicio N°27 Hacer un componente que calcule la velocidad a mover en base al input del eje Vertical, suavice la velocidad y se la pase a un blend tree 2d. Ejercicio N°28 Hacer un componente que calcule las velocidades de mover y rotar en base al input de los ejes Vertical y Horizontal, suavice las velocidades de rotación y aceleración, y se las pase a un blend tree 2d. Ejercicio N°29 Hacer un componente que calcule las velocidades de mover y rotar en base al input des eje Vertical y la presión de dos teclas para rotar, suavice las velocidades de rotación y aceleración, y se las pase a un blend tree 2d. 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 Daño Localizado 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 Headshots El sistema de daño que estuvimos utilizando anteriormente servía para muchos juegos, pero en muchos otros juegos, donde apuntar es la principal habilidad, ese sistema no sirve. Necesitamos hacer que el daño sea localizado, o sea, que dependiendo de en donde disparemos, el daño sea uno u otro. Para lograr ello mezclaremos una serie de instrucciones nuevas con técnicas vistas anteriormente. Área de daño Anteriormente para delimitar áreas de daño con un BoxCollider alcanzaba, pero un personaje tiene una figura un poco más compleja, y claramente no podemos disparar entre medio de las piernas y que sea considerado un disparo. También vimos que usar Mesh Collider no es una buena idea porque es costoso, y más aun con un personaje con tanto detalle. Otro detalle es que por más que usemos Mesh Collider, este no se adapta a las animaciones y, por último, por más que lo haga, no podremos diferenciar en que parte chocó la bala. En esta unidad vimos que un modelo 3d puede tener huesos, y que dichos huesos no son más que objetos vacíos, esto combinado con emparentamiento puede ser de gran ayuda. En los FPS lo que se suele hacer es emparentar cajas a los diferentes huesos de los enemigos y personajes. Al estar emparentados a los huesos, y estos al moverse, hacen que el personaje forme su figura con una serie de cajas que se adaptan a la forma. Como vemos en la imagen también pueden ser esferas y capsulas, aunque estás pueden llegar a ser un poco más costosas que las cajas por lo que por el momento recomendaría cajas. Un detalle a tener en cuenta es que no es conveniente agregarle el BoxCollider directamente a los huesos, porque puede ser que los huesos no vengan con la orientación que pensamos y no estén alineados, conviene emparentar directamente la caja al hueso. 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 Ejercicio N°30 Tomar un personaje humanoide y emparentarle suficientes cajas en los huesos para cubrir todo su cuerpo. Generalmente van en los pies, manos, cabeza, pantorrillas, muslos, pelvis, estómago y pecho, o sea, en todas las partes articuladas 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 Redirigir el daño Hay un pequeño problema a la hora del infligir el daño. Hasta ahora lo que hacíamos era colisionar con el collider del objeto, y hasta ahora teníamos todos los componentes en un solo objeto, o sea, los colliders y el componente que administraba la vida. Antes simplemente hacíamos GetComponent al objeto al cual chocamos y obteníamos el componente de la vida, pero ahora es diferente, ya que los colliders se encuentran en cajas emparentadas a los huesos. Un humanoide va a tener muchos objetos emparentados entre sí, por lo que una duda que nos puede surgir es en donde poner el componente Vida. En estos casos conviene poner los componentes que representan aspectos del objeto entero en el objeto padre de todos, o sea, el que contiene todo lo demás. En este caso tendríamos el componente vida en el objeto padre, pero los colliders del personaje en objetos hijos de los huesos, que a su vez son hijos del padre. Si lanzamos un rayo y chocamos contra los colliders hijo e intentamos hacer GetComponent del componente Vida, nos va a devolver null, o sea, no va a encontrar el componente, ya que no está en ese objeto, está en un objeto padre. En este caso, para solucionar el problema, utilizaremos la función GetComponentInParent, la cual busca un componente en el objeto, pero si no lo encuentra comienza a buscar en el padre del objeto, y si no, en el padre del padre, y así sucesivamente hasta encontrarlos en algún ancestro, o no encontrarlo y devolver null. Recordemos que en nuestro caso ahora estamos disparando con rayos, por lo que haríamos GetComponentInParent del collider de donde choco el rayo. Otra cosa que vale la pena destacar es que es importante que haya solamente UN componente vida, ya que, si nosotros ponemos el componente Vida en cada collider, es como si cada parte del cuerpo tuviese su propia vida, y en realidad todo el objeto posee una sola. 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 49 Ejercicio N°31 Hacer un objeto vacío emparentado a otro. Agregar al padre un componente con una propiedad float. Agregar al hijo un componente que en el Awake acceda al componente del padre y la cambie la propiedad float. Ejercicio N°32 Hacer un objeto vacío emparentado a otro. Agregar al hijo un componente que cada vez que se presione una tecla mueva al padre en vez de a sí mismo. Ejercicio N°33 Hacer un objeto vacío que tenga una caja de hijo. Hacer un componente que tire un rayo y que destruya al objeto padre del collider que chocó, en vez de solamente al collider. 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 50 Atenuar el daño Con la modificación que hicimos ahora podremos disparar en cualquier parte del cuerpo del enemigo y sacarle vida, pero nos falta un detalle. La mayoría de los juegosFPS discrimina el daño a infligir dependiendo de donde se dispara, para ello debemos de alguna manera agregarle información al collider de cuanto porcentaje del daño va a recibir el objeto. Al igual que cada vez que necesitamos agregar alguna propiedad a un objeto, podemos crear un componente con dicha información, en este caso podríamos llamarlo DamageReceiver o algo por el estilo. Este componente podría tener una propiedad llamada “atenuation” (atenuación) que sea una propiedad cuyo valor oscile entre 0 y 1, indicando el porcentaje. Luego, el componente que tira el rayo, aparte de hacer GetComponentInParent para obtener el componente vida y restarle el daño deseado, puede hacer GetComponent al collider para obtener su DamageReceiver, ya que la idea es que cada parte del cuerpo tenga una atenuación diferente. Una vez que obtuvo la atenuación puede simplemente multiplicar el daño del componente que dispara, por la atenuación del componente que la indica en el collider, para finalmente restarle el resultado a la vida que está en los padres del collider. Si bien esta forma seria la correcta, hay una forma más prolija de hacer esto. Como vimos anteriormente, todo componente tiene una serie de instrucciones las cuales nos permiten interactuar con ellos. Nosotros podríamos hacer una instrucción en el componente DamageReceiver o Atenuador, el cual reciba por parámetro la cantidad de daño que queremos infligir y luego dicha instrucción se encargue de multiplicar el daño recibido por la atenuación y redirigirla al componente Vida padre. 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 51 Para crear una instrucción hacemos lo mismo que al crear un evento. En este caso creamos una llamada RecibirDaño, y por parámetros especificamos uno de tipo float. Esto implica que cuando quieran ejecutar la instrucción hace falta que nos indiquen cuánto. Luego la instrucción del componente se pide a si mismo su componente Vida que se encuentra en los padres y le resta el daño que recibió por parámetros multiplicado por la atenuación. Para ejecutar la instrucción lo hacemos al igual que cuando ejecutamos alguna instrucción de algún componente, usamos la sintaxis de punto sobre una variable que esté conectada a un componente de este tipo y ejecutamos la instrucción pasándole los parámetros. 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 52 Ejercicio N°34 Hacer un componente que tenga una función que use print para decir Hola. Hacer otro componente que tenga una propiedad del tipo del componente anterior y que ejecute la función cada vez que se presione una tecla. Agregar dos componentes a un objeto y conectar la propiedad del segundo componente al primer componente. Ejercicio N°35 Agregar a una caja un componente con una función que lo mueva para adelante. Hacer un componente que tire un rayo y acceda al componente anterior y ejecuta la función. Ejercicio N°36 Hacer un objeto vacío con el componente Vida. Emparentarle una caja con un componente que tenga una función la cual le quite 10 de vida al componente Vida del padre. Hacer un componente que tire un rayo y ejecute la función de daño. 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 53 Bibliografía utilizada y sugerida Recursos Online Videotutoriales de la interfaz de Unity. http://unity3d.com/es/learn/tutorials 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 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 54 Lo que vimos: En esta unidad hemos visto: 1. Cómo importar un modelo humanoide con huesos. 2. Cómo utilizar el sistema de animaciones para mover dichos huesos. 3. Cómo controlar animaciones desde el editor y por código. 4. Cómo utilizar Rayos, Colliders y Emparentamiento para hacer un sistema de daño localizado. 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 55 Lo que viene: Ahora que ya sabemos utilizar animaciones, podemos animar a nuestro personaje, pero como vimos, dichas animaciones deben ser controladas por la lógica de movimiento del mismo. En las próximas unidades comenzaremos a ver cómo hacer para que nuestro enemigo comience a pensar y tomar decisiones por sí mismo, para que, luego, estas decisiones se las comunique al sistema de animación