En esta serie de artículos hablaré sobre cómo y por qué decidimos crear nuestra propia solución para importar animaciones flash a Unity, sobre las optimizaciones y la cocina interna del complemento resultante. Y también en el programa: una historia sobre el interior del formato swf, las características de la extensión del editor de Unity y, en general, sobre animaciones en general. Pido un corte!

Introduccion
Al comienzo de cualquier proyecto están los dolores de elección de tecnología para muchas de sus partes. Una de esas partes es el sistema de animación. Hay varias variables de las que depende esta elección. En primer lugar, con qué están acostumbrados (pueden) trabajar sus animadores o qué herramientas de estos animadores son más fáciles de encontrar. Está claro que no tiene sentido elegir un producto extremadamente específico, porque si los empleados actuales se van por una razón u otra (¿un autobús repentino?), Será extremadamente difícil reemplazarlos, parte del proyecto simplemente se detendrá indefinidamente, lo que, en el caso de un producto comercial Puede ser muy costoso. La segunda variable es más técnica: integración en su motor. ¿Existen soluciones de terceros y la calidad de estas soluciones? ¿Existe alguna fortaleza y capacidad para crear la mía propia, así como la productividad y la conveniencia de todo lo anterior? Bueno, la tercera variable son las capacidades de esta herramienta, porque si usted, hemorragias nasales, necesita cinemática inversa , entonces es absolutamente extraño elegir animación no esquelética.
Tipos de animaciones 2D
Considere las opciones más populares para implementar animaciones en juegos. Solo hablaré sobre animaciones en 2D, animaciones en 3D: este es el tema de una conversación, enfoques y herramientas completamente diferentes. Puede omitir una sección sin temor si es experto en estos asuntos (no habrá revelaciones ni averías), o si ha tratado de ver las características de las animaciones flash, están a continuación.
Animaciones de cuadros
Nuestra mini revisión se abre con el tipo de animación más simple y antiguo: animación cuadro por cuadro. Cada cuadro de dicha animación está representado por una imagen separada, con un cambio rápido del cual surge una ilusión de movimiento.
Pros:
Una implementación elemental, generalmente en cualquier motor. Cualquier complejidad y estilo de animaciones, al menos diseña e inserta una película en cuadros (en teoría, por supuesto). Cualquier herramienta: casi cualquier cosa puede darle una secuencia de marcos que, si es necesario, se pueden pegar en un atlas de textura.
Contras:
El principal inconveniente es, por supuesto, el tamaño de estas cosas en la memoria. Naturalmente, hay todo tipo de trucos, como cortar cuadros en bloques y la reutilización posterior de bloques repetidos, cargar en segundo plano cuadros desde el disco y liberarlos, y otros. Pero estos trucos tienen sus inconvenientes. El corte en bloque, adecuado solo para pixel art , carga en segundo plano, crea una carga adicional en el disco, ocupa mucho espacio en este disco y el tamaño de su juego aumenta, así como la cantidad de datos descargados para iniciar o actualizar.
Total:
Solo es adecuado para animaciones de tamaño pequeño y número de cuadros, idealmente para pixel art y el estilo de juegos retro a la NES .
Animaciones de video
Como la apoteosis de la locura de las animaciones cuadro por cuadro, aparecen animaciones de video. Y sí, se usa e incluso ocasionalmente para el lugar. Implementamos esto para juegos en el género " Objetos ocultos " para animaciones grandes y complejas, así como para escenas cortadas con un toque de realismo. Con la ayuda de códecs como theora y vp8, puede implementar animaciones de video bastante tolerables (e incluso con un canal alfa ) usted mismo.
Las ventajas aquí, por supuesto, es que puedes mostrar en tales animaciones todo lo que tu corazón desea, desde escenas dirigidas con la participación de actores reales, hasta batallas en 3D. Las desventajas son la carga salvaje en la CPU al decodificar esto y, por supuesto, la calidad de la imagen. Puede encontrar un compromiso entre calidad y rendimiento en casos muy limitados y específicos, como en los juegos indicados anteriormente para objetos ocultos, por ejemplo.
En general, está lejos de ser adecuado para todos y está lejos de ser siempre, o más bien casi nunca, si no consideramos escenas cortadas renderizadas, ¿dónde está el lugar para tales "animaciones"? Una buena implementación de tales animaciones tampoco puede presumir de simplicidad, hay muchos matices y trucos, tanto en términos de la calidad de la imagen de salida como de las cargas recibidas en el procesador central. Debido a la especificidad, hay pocas implementaciones listas, tampoco difieren en calidad, o cuestan mucho dinero (hola, Bink_Video ), por lo que muchas escriben las suyas.
Animaciones esqueléticas
Así que llegamos a los tipos populares y modernos de animaciones 2D. Las animaciones esqueléticas capturan cada vez más los corazones y las mentes de los desarrolladores en el campo de 2d, convirtiéndose en la animación estándar para juegos. Es curioso que llegaron tan ampliamente en 2d relativamente recientemente, a diferencia de 3d, donde aparecieron durante la época de King Peas, cuando los padres escribieron Half-Life . La esencia de las animaciones esqueléticas, por extraño que parezca, está en el esqueleto, que crea un animador a partir de huesos conectados entre sí por una estructura de árbol. Los fragmentos se unen a los huesos en forma de imágenes separadas. Toda la estructura se pone en movimiento mediante desplazamientos y rotaciones de los huesos entre sí. Los desplazamientos y rotaciones de los huesos en el esqueleto siguen la línea de tiempo de animación general.
Las ventajas son obvias: no necesitamos almacenar cada fotograma de la animación en forma de imágenes separadas, solo fragmentos (los brazos y las piernas del personaje, por ejemplo), que moveremos los huesos del esqueleto. Hay excelentes implementaciones de este tipo de animación con tiempos de ejecución para las plataformas y motores necesarios, con un precio de uso razonable o incluso gratis: Spine , Spriter , Anima2D , DragonBones y otros. Gracias al esqueleto y sus características, se puede lograr una suavidad colosal de las animaciones al interpolar las posiciones de sus huesos, así como al mezclar transiciones de animación a animación e incluso mezclar dos animaciones diferentes: disparar a la carrera, disparar a escondidas, etc. No enumeraré todas las posibilidades de la animación esquelética, realmente hay muchas y son geniales. Será mejor que les dé un enlace donde se muestren claramente con imágenes y descripciones en el sitio web de Spine .
Parece una bala de plata, pero no. Hubo algunos inconvenientes. Inmediatamente haga una reserva que para muchos proyectos y animaciones, estas desventajas pueden no existir. Si las animaciones esqueléticas te convienen, es genial, úsalas, son hermosas y modernas.
Volvamos a las desventajas. Una etapa adicional en la creación de animación es el aparejo (o el aparejo, como muchos términos en nuestra industria, también se rusificó). La creación misma del esqueleto y la unión de los huesos a los fragmentos. Si el objeto tiene una animación, y no varias, como, por ejemplo, el personaje del juego en el género " Plataformas ", entonces el escenario es completamente superfluo. No todas las animaciones están convenientemente animadas con huesos. Hay muchas animaciones donde los huesos se interponen y sin ellas es más conveniente y más rápido, tanto en términos de creación como en términos de rendimiento del juego. Un artículo separado sacaré especialistas en el mercado. Su número está creciendo con la popularidad de la animación esquelética, pero aún no es una tarea fácil encontrarlos en su equipo. La propagación de herramientas y herramientas también afecta, alguien está acostumbrado y usa uno, alguien más, es necesario volver a entrenar sobre la marcha, lo que crea dificultades adicionales para encontrar y capacitar a los empleados.
Animaciones de línea de tiempo
Llevé este tipo de animación hasta el final, no porque sea mejor que todos los demás, sino porque son solo las animaciones flash sobre el interior que se discutirán en la parte técnica del artículo. Flash no es el único representante de este tipo de animación, pero ciertamente es su líder, por lo que todo se describirá al respecto. Las animaciones de la línea de tiempo consisten en fragmentos que se animan en capas separadas en una línea de tiempo. Casi lo mismo que vimos en la animación esquelética, pero sin esqueleto. De acuerdo con los fotogramas clave en la línea de tiempo, podemos mover, rotar, reemplazar, dibujar nuevos fragmentos en estos fotogramas y, por supuesto, interpolar la separación silábica, la escala y la rotación entre ellos. Es decir, no movemos los huesos con los fragmentos adjuntos, sino los fragmentos en sí. Por supuesto, perdemos muchas de las oportunidades que nos brindan las animaciones esqueléticas, pero no todos las necesitan. A cambio, adquirimos otros, como:
- la capacidad de dibujar e insertar nuevos fragmentos en el medio de la animación;
- sin aparejo, sin huesos que a veces solo interfieren;
- Adobe Flash (ahora Adobe Animate ) es la herramienta de animación más antigua y más probada durante años, una gran cantidad de animadores, de una forma u otra, la poseen;
- la capacidad de usar animaciones antiguas al traducir sus proyectos flash a Unity, incluidas las animaciones realizadas en gráficos vectoriales , y no solo en rásteres .
¿Flash está muerto? Como jugador en los navegadores, ciertamente, como una herramienta para animaciones, vivo y bien, no hay alternativas y no se espera. Contras? Por supuesto El principal inconveniente es que esto no es animación esquelética, ¿eh? Nos privamos de la oportunidad de mezclar animaciones entre nosotros, no tenemos cinemática inversa y capacidades similares inherentes solo al esqueleto. ¡Pero tenemos líneas de tiempo anidadas entre sí, así como máscaras de trama y vectores! ¡Todos los animadores adoran las máscaras! Aquí vale la pena mencionar que en Spine, recientemente aparecieron capacidades de recorte , pero hasta ahora solo geométricas y muy limitadas en comparación con las máscaras de flash.
Resumen del tipo de animación
Naturalmente, no enumeré todos los tipos de animaciones, solo las principales. Por ejemplo, las llamadas animaciones de procedimiento se quedaron atrás, cuando los objetos o sus fragmentos se ponen en movimiento solo por código, pero no es posible contrastarlos con otros, y realmente no quería inflar el artículo, es mejor ver algo más especializado en animaciones para completar la imagen
Para resumir. No hay bala de plata, como siempre y en casi todo. Debe elegir el proyecto, las tareas y las personas. Después de todo, nadie restringe a nadie el uso de un tipo de animación. En todas partes hay proyectos donde se utilizan todo tipo de animaciones al mismo tiempo y todos están contentos. Escenas cortadas - video, personajes - esqueleto, escenario - línea de tiempo, vuelos de emisores de sistemas de partículas - procesales, las partículas mismas en sus sistemas - cuadro por cuadro. Tomamos lo mejor de cada tipo.
La agonía de la elección y la decisión de escribir la suya.
Bueno, por algunas razones objetivas, decidimos que necesitábamos animaciones flash para nuestro proyecto. Se planteó la cuestión de integrarlos en el motor. Después de probar varias opciones de complementos, nos decidimos por uno que nos convenía con sus capacidades, estaba vivo y era compatible, y también tenía un precio completamente inmoderado para una licencia entre licencias, pero puede tolerar un buen producto. Intencionalmente no daré ningún nombre, para no hacer publicidad o anti-publicidad a nadie.
Con este complemento, vivimos durante casi un año de desarrollo, durante el cual se aclararon los detalles, que no pudimos usar más. A saber, la calidad de su integración en Unity. Todo resultó en errores francamente graves que no se puede decir que sean fáciles, rápidos y sin una pelea reparada por parte de los desarrolladores, y en un rendimiento terrible en los dispositivos de destino, y todavía tenemos el nivel de iPad 2 . Esto sucedió debido a la integración analfabeta en un motor específico, la ignorancia de sus detalles y dificultades, estábamos más que satisfechos con las posibilidades, pero los códigos fuente, incluso en un orden personal, se negaron a abrir, y se decidió escribir nuestra decisión.
Tenía una experiencia bastante exitosa escribiendo extensiones para Unity y tenía poca experiencia en convertir animaciones flash a mis formatos. Esto último fue hace mucho tiempo, pero se recordó algo. En el mismo lugar, se decidió escribirlo todo como un proyecto hogareño, para no depender del proyecto o de la empresa donde trabajo, y para ser sincero, también quería tener mi propio producto. Entonces, armado con una especificación de formato swf de 250 páginas, fui a la batalla.
Opciones de exportación
Para empezar, vale la pena discutir opciones para exportar animaciones desde el editor de flash. Hay varios de ellos, naturalmente con sus ventajas y desventajas. Veamos los principales.
formato .xfl
En el editor de animación flash, es posible guardar la fuente de animación en un formato .xfl sin comprimir en lugar del formato cerrado .fla, que se ofrece de manera predeterminada. El formato es bastante simple pero indocumentado. Consiste en varios directorios anidados y un montón de archivos .xml, donde se describen todos los estados de los clips almacenados en su interior. El formato de descripción también es simple y claro, aquí hay un ejemplo:
static_clip.xml
<DOMSymbolItem name="static_clip" itemID="5c719f28-00000051" lastModified="1550950184"> <timeline> <DOMTimeline name="static_clip"> <layers> <DOMLayer name="Layer_1" color="#00FFFF" current="true" isSelected="true"> <frames> <DOMFrame index="0" keyMode="9728"> <elements> <DOMBitmapInstance selected="true" libraryItemName="bitmap.png"/> </elements> </DOMFrame> </frames> </DOMLayer> </layers> </DOMTimeline> </timeline> </DOMSymbolItem>
Enlace a la fuenteAquí tenemos un clip estático static_clip
con una capa Layer_1
y un marco, en el que hay un mapa de bits llamado bitmap.png
.
movie_clip.xml
<DOMSymbolItem name="movie_clip" itemID="5c719f30-00000053" lastModified="1550950713"> <timeline> <DOMTimeline name="movie_clip"> <layers> <DOMLayer name="Layer_1" color="#00FFFF" current="true" isSelected="true"> <frames> <DOMFrame index="0" duration="4" tweenType="motion" motionTweenSnap="true" keyMode="22017"> <elements> <DOMSymbolInstance libraryItemName="static_clip"> <matrix> <Matrix tx="-50" ty="-50"/> </matrix> <transformationPoint> <Point x="28.5" y="27.5"/> </transformationPoint> </DOMSymbolInstance> </elements> </DOMFrame> <DOMFrame index="4" tweenType="motion" motionTweenSnap="true" keyMode="22017"> <elements> <DOMSymbolInstance libraryItemName="static_clip" centerPoint3DX="128.5" centerPoint3DY="127.5"> <matrix> <Matrix tx="100" ty="100"/> </matrix> <transformationPoint> <Point x="28.5" y="27.5"/> </transformationPoint> </DOMSymbolInstance> </elements> </DOMFrame> </frames> </DOMLayer> </layers> </DOMTimeline> </timeline> </DOMSymbolItem>
Enlace a la fuenteAquí describimos el clip de animación movie_clip
, que contiene dos fotogramas clave con índices 0 y 4, respectivamente. Los cuadros contienen nuestro clip estático static_clip
en las coordenadas (-50;-50)
y (100;100)
. Entre cuadros hay movimiento de interpolación (animación de procedimiento, en nuestro caso es solo una transferencia, sin escala y rotación), respectivamente, la posición de un clip estático entre cuadros clave se puede obtener por interpolación lineal de coordenadas de estos cuadros.
Naturalmente, todo estará en animación real, ejem ... un poco más complicado y más voluminoso, pero puedes resolverlo todo sin documentación. Parece que aquí está la felicidad. Y conozco varios proyectos y empresas que tuvieron éxito en este sentido, pero con algunas limitaciones y dificultades. Estas dificultades son la mosca en la pomada .xfl, a saber:
- Las interpolaciones (interpolaciones, rusificado como pudo) son muy diferentes, ambas simples: con interpolación lineal, y más complejas: con funciones definidas por el usuario y gráficos de esta interpolación, transformando gráficos vectoriales en gemelos, con sus propias reglas solo para macromedia y adobe;
- Los gráficos vectoriales, como todas las animaciones, excepto los gráficos de trama, se describen en forma de texto, por ejemplo . En consecuencia, es necesario escribir su propio rasterizador, que, debido a las complejidades y características del vector en flash, no es posible en la práctica;
- Las reglas para reproducir animaciones, incluidas las anidadas, debe pensar desde cero, no hay documentación para ello y cuándo se debe mostrar qué fotograma, qué ajustar en qué situaciones y qué dejar sin interpolación: queda por determinar mediante experimentos largos, tratando de cubrir todos los casos posibles en las pruebas se ejecutan, lo cual es un ejercicio muy poco trivial para una solución general, en lugar de privada.
Estas no son todas las dificultades de este enfoque, pero son suficientes para comprender que, para una solución general, solo es adecuado con fuertes reservas. Érase una vez, tomé este camino para uno de los proyectos en los que participé. Hubo escenas de corte flash, con gemelos clásicos (sin reglas de interpolación personalizadas y funciones especiales de esta interpolación), solo gráficos de mapa de bits y sin otras características avanzadas que proporciona el editor de flash. La solución privada fue escrita de manera bastante rápida y eficiente, pero los animadores tuvieron que ser severamente limitados para que no usaran nada más o menos complicado. El enfoque tiene derecho a la vida y hay varias bibliotecas, de diversos grados de negligencia, basadas en él, pero, como dije, con muchas reservas y limitaciones.
scripts .jsfl
Otra opción, casi funcional, es obtener información sobre nuestras animaciones. Los scripts jsfl le permiten expandir el editor flash, interactuar con su entorno, cambiar la animación y, por supuesto, obtener toda la información necesaria sobre líneas de tiempo, capas, clips y marcos en ellos. Y también lo usan los animadores para automatizar varias acciones, pero esta es una historia de un libro vecino. En general, el enfoque está dotado de todas las desventajas del enfoque anterior, por lo que no me detendré en él, solo puedo decir que con él puedes descargar toda nuestra animación en forma de, por ejemplo, animación cuadro por cuadro, y esta no es la forma de un Jedi real (pero, naturalmente, tiene lugar en algunos proyectos). Volveremos a estos scripts en el enfoque que elegí: rasterizar gráficos vectoriales y optimizar la animación paginada.
Aplicación AIR
Pero este enfoque ya está funcionando bastante y puede usarse como debería. No lo elegí, pero como referencia daré esta opción. La esencia del enfoque es que creamos una aplicación AIR en flash o, por ejemplo, en Haxe , por ejemplo, que obtendrá toda la información de una animación ya compilada en formato swf. Reproducimos la animación cuadro por cuadro dentro de nuestra aplicación, obtenemos toda la información del cuadro y la guardamos en el formato que necesitamos para nuestro tiempo de ejecución. Aquí se resuelven todos los problemas anteriores:
- no es necesario rasterizar gráficos vectoriales, el tiempo de ejecución de flash lo hará por nosotros, solo queda obtener esta información y guardar el resultado de los fragmentos vectoriales;
- no es necesario inventar reglas de juego y lidiar con la interpolación gemela personalizada, el reproductor flash dentro de la aplicación AIR sabe exactamente cómo hacer esto y hará casi todo por nosotros;
Como beneficio adicional, tenemos la oportunidad de usar scripts de cuadros en animaciones (todo tipo de play()
, stop()
y otros gotoAndPlay()
, algunos animadores los aman mucho). La desventaja es la imposibilidad de exportar las animaciones en bucle en el flash en sí, pero esto no importa, ya que puede hacer un bucle en su tiempo de ejecución y pedir a los animadores que preparen todo para esto.
Vale la pena mencionar que estoy seguro de que todo será un poco más complicado de lo que parece en mi descripción, ya que personalmente no fui allí, por lo que no puedo decirle los detalles. ¡Dejen que aquellos que han pasado por este camino compartan sus experiencias, con gusto leemos sobre sus alegrías y tribulaciones!
Flash player propio
Esta es probablemente la opción más honesta, obvia y directa de todas, pero también la más difícil. Al final, esto es lo que hace un reproductor flash real, que la mayoría de nosotros tenemos en nuestro navegador favorito como complemento. Representantes populares de este género: gameswf y, a partir del anterior, scaleform . Ambos ahora están muertos. Es interesante que se utilizaron principalmente para implementar la GUI en varios proyectos, incluido AAA . Pero estamos interesados en la estructura interna, no en las aplicaciones específicas de las bibliotecas muertas.
Cualquier reproductor flash que se respete tiene al menos las siguientes cosas a bordo:
- analizador de formato swf;
- gráficos vectoriales rasterizadores;
- implementación de una máquina virtual para ejecutar código ActionScript ;
- implementación de una biblioteca estándar para código de usuario;
Cada uno de estos puntos grita sobre si es posible implementarlo, entonces tendrá que cambiar a más de un equipo para esta tarea e intercambiar varios años de desarrollo a la versión mínima. Incluso la implementación de una pequeña parte, suficiente para jugar algo, llevará mucho tiempo, y las dificultades adicionales, en forma de tantas partes indocumentadas de todo este proceso, duplicarán este período ya enorme.
Sí, la red está llena de intentos de implementar cada una de estas partes, con diversos grados de negligencia y agravación. Pero ni siquiera es posible tomar estos desarrollos como base, solo llevará años detectar errores a partir de ahí y escribir pruebas unitarias no escritas antes de darse cuenta de que no será posible realizarlo completamente. Aquellos que intentaron complementar gameswf con las capacidades necesarias entienden de lo que estoy hablando. Un flash player honesto también tiene que rasterizar los gráficos vectoriales no de antemano, sino en tiempo de ejecución, lo que afectará a tal éxito de rendimiento que no todos los proyectos pueden sobrevivir. Aprovecho esta oportunidad para transmitir mis saludos a los sobrevivientes que usaron Scaleform en dispositivos móviles. En general, la forma más sombría y desesperada, no es nuestra elección.
Combinamos enfoques
Así que finalmente llegó a mi opción. Habiendo estudiado las posibles formas, se dibujó una combinación interesante para mí. Relativamente simple de implementar, factible para una persona en volumen y al mismo tiempo lo suficientemente funcional como para cubrir las necesidades de la mayoría de las animaciones de línea de tiempo 2D.
En primer lugar, utilizaremos la animación compilada en swf para no tener varias opciones de reproducción y casi nunca adivinar cómo funciona el reproductor flash desde adentro, ya que no podemos cubrir todos los casos posibles, pero tratamos de escribir una solución general. Además, el editor flash se deshace de todos los gemelos que se usaron en la animación, representando hábilmente, en el swf compilado, las posiciones desnudas de los fragmentos.
En segundo lugar, prohibimos el uso de scripts en animaciones. Sí, este es un requisito muy difícil y triste, pero no tengo un equipo de programadores para implementar una máquina virtual honesta y una biblioteca estándar que tendría que escribir casi a ciegas. Aquí, por supuesto, el menos de mi enfoque es visible en comparación con el enfoque donde se usó la aplicación AIR, ya que en este último se podrían usar algunos scripts para la reproducción de animación interna. Por otro lado, no interfiere con la creación de buenas animaciones. Para transferir información personalizada de la animación al juego, puede usar las llamadas frame labels
, que serán visibles desde el código, así como colgar eventos personalizados en fotogramas específicos en forma de funciones de devolución de llamada que ya usan tiempo de ejecución.
En tercer lugar, nos deshacemos de escribir nuestro propio rasterizador de gráficos vectoriales, por la incapacidad de escribir uno para el caso general, para cubrir todas las opciones y capacidades del vector en flash. En su lugar, rasterizaremos los gráficos a (!) Compilación utilizando un script jsfl. Al mismo tiempo, con la ayuda de este script, optimizaremos nuestros gráficos vectoriales al fusionar clips estáticos en una imagen, reducir o aumentar las imágenes de mapa de bits resultantes para nuestras necesidades: calidad y / o rendimiento. Aquí también vale la pena recordar las diversas opciones para la calidad / resolución del arte para dispositivos con diferentes densidades de píxeles en la pantalla (por ejemplo, arte HD y SD).
La conclusión de la parte lírica.
Esto concluye la primera parte del artículo. En la segunda parte habrá detalles técnicos de implementación, piezas de código, imágenes (!), Optimizaciones, trucos y trucos. Próximamente en sus pantallas, ¡no se lo pierdan! Al final, daré un par de enlaces interesantes con información sobre el uso de animaciones flash de colegas, afortunadamente de ZeptoLab y Playrix .