Animaciones de modelos 3D
Cómo animar modelos 3D en tu escena
Los modelos 3D en .glTF y .glb pueden incluir tantas animaciones como quieras. Las animaciones le indican al mesh cómo moverse, especificando una serie de keyframes que se distribuyen a lo largo del tiempo; luego el mesh mezcla una pose con otra para simular un movimiento continuo.
La mayoría de las animaciones de modelos 3D son skeletal animations. Estas animaciones simplifican la geometría compleja del modelo a una "figura de palitos", vinculando cada vertex en el mesh al bone más cercano en el skeleton. Los modeladores ajustan el skeleton a distintas poses, y el mesh se estira y se dobla para seguir estos movimientos.
Como alternativa, vertex animations animan un modelo sin necesidad de un skeleton. Estas animaciones especifican directamente la posición de cada vertex en el modelo. Decentraland también soporta estas animaciones.
Ver Animations para ver detalles sobre cómo crear animaciones para un modelo 3D. Lee Shape components para instrucciones sobre cómo importar un modelo 3D a una scene.
Comprueba si un modelo 3D tiene animaciones
No todos los glTF files incluyen animaciones. Para ver si hay alguna disponible, puedes hacer lo siguiente:
Si usas VS Code(recomendado), instala la GLTF Tools extensión y allí visualiza el contenido de un archivo glTF.
Abre el Babylon Sandbox sitio y arrastra el archivo glTF (y cualquier .jpg o .bin dependencia) al navegador.
Abre el .glTF archivo con un editor de texto y desplázate hacia abajo hasta que encuentres "animations":.
Reproducción automática
Si un modelo 3D incluye alguna animación, el comportamiento predeterminado es que la primera de ellas siempre se reproduce en loop.
Para evitar este comportamiento, agrega un Animator component a la Entity que tiene el modelo, y luego maneja la reproducción de las animaciones explícitamente. Si un Animator component está presente en la Entity, todas las animaciones pasan por defecto a un estado playing: false y deben reproducirse manualmente.
Maneja las animaciones explícitamente
Un Animator component se usa para acceder a todas las animaciones de la Entity y puede usarse para indicar explícitamente a la Entity que reproduzca o detenga una animation. El Animator component incluye un array de states, esta lista debe incluir un objeto por cada una de las animaciones que el modelo 3D puede realizar. Un solo Animator puede incluir tantos states como sea necesario.
Cada state object lleva un registro de si una animación se está reproduciendo actualmente.
📔 Nota: El Animator component debe importarse mediante
import { Animator } from "@dcl/sdk/ecs"
Ver Importaciones para ver cómo manejarlos fácilmente.
Obtener una animación
Obtén un clip del Animator por nombre usando la función .Animator.getClip() Esta función devuelve una versión mutable del objeto de estado de animación.
Animator.getClip requiere los siguientes parámetros:
entity: La Entity delAnimatorcomponent que quieres consultar.clipName: String con el nombre del clip que quieres obtener.
Animator.getClip obtiene una versión mutable del estado de la animación, por lo que puedes modificar libremente los valores que devuelve esta función.
📔 Nota: Si intentas usar Animator.getClip() para obtener un clip que no está listado en el Animator component, arroja un error. Usa Animator.getClipOrNull() si prefieres obtener una respuesta null en ese caso, en lugar de un error.
Reproducir una animación
El .playing campo en un estado de animación determina si la animación se está reproduciendo actualmente. Ten en cuenta que varias animaciones pueden estar reproduciéndose en un mismo modelo 3D al mismo tiempo.
Usa la Animator.playSingleAnimation() función en un AnimationState object.
Si la Entity estaba reproduciendo otras animaciones, Animator.playSingleAnimation las detiene.
Animator.playSingleAnimation requiere los siguientes parámetros:
entity: La Entity delAnimatorcomponent que quieres afectar.clipName: String con el nombre del clip que quieres reproducir.resetCursor: (opcional) Si true, reproduce la animación desde el principio, incluso si antes estaba en pausa. Si falseseguirá reproduciendo la animación desde donde se pausó. Predeterminado: true.
La siguiente tabla resume cómo Animator.playSingleAnimation() se comporta, usando distintos valores para la resetCursor propiedad:
resetCursor = false
resetCursor = true (predeterminado)
Se está reproduciendo
No tiene efecto.
Se reproduce desde el principio.
En pausa
Se reanuda desde el último frame reproducido.
Se reproduce desde el principio.
Terminada (sin loop)
Se reproduce desde el principio.
Se reproduce desde el principio.
Animaciones en loop
Por defecto, las animaciones se reproducen en un loop que repite la animación indefinidamente.
Cambia esta configuración ajustando la loop propiedad en el state object.
Si loop se establece en false, la animación se reproduce una sola vez y luego se detiene, quedándose en la postura del último frame.
Detener una animación
Para detener todas las animaciones que una Entity está reproduciendo, usa Animator.stopAllAnimations().
Animator.stopAllAnimations requiere los siguientes parámetros:
entity: La Entity delAnimatorcomponent que quieres afectar.resetCursor: (opcional) Si true, vuelve a la postura del primer frame de la animación. Si false, permanece en pausa en su postura actual. Predeterminado: true.
📔 Nota: Al reproducir una animación con Animator.playSingleAnimation, esta función se encarga de detener todas las demás animaciones internamente. No necesitas detener explícitamente las otras animaciones en ese caso.
Cuando una animación termina de reproducir una animación sin loop, por defecto el modelo 3D permanece en la última postura que tenía. La shouldReset propiedad controla qué sucede cuando una animación detenida se vuelve a reproducir: si true, la animación se restaura a su estado inicial (su primer frame, o su último frame si se reproduce con una speed) cada vez que pasa de detenida a en reproducción. Si false (predeterminado), se reanuda desde donde estaba.
También puedes usar Animator.stopAllAnimations() en cualquier momento para restablecer explícitamente la postura al primer frame de la animación.
📔 Nota: Restablecer la postura es un cambio brusco. Si quieres que el modelo transicione suavemente a otra postura, reproduce la otra animación y mezcla entre ambas desplazando gradualmente sus weight propiedades weight. Ver Animation weight.
Detectar cuándo termina una animación
Cuando una animación sin loop termina de reproducirse, por defecto el engine establece la playing propiedad de nuevo en false. El código de tu scene puede leer este valor para saber cuándo terminó la animación, por ejemplo para encadenar otra animación justo después.
📔 Nota: Al consultar el estado de la animación en cada frame, léelo siempre mediante Animator.get() (solo lectura). No uses Animator.getClip() o Animator.getMutable() para la consulta: devuelven una versión mutable del component, lo que lo marca como cambiado en cada frame y provoca trabajo de sincronización innecesario.
El playing La propiedad solo cambia por el engine cuando la animación termina por sí sola. Las animaciones en loop se reproducen hasta que se detienen, por lo que nunca cambian la propiedad por sí mismas, y las animaciones con speed establecida en 0 nunca terminan.
📔 Nota: Esta función solo es compatible con el cliente Desktop.
Manejar varias animaciones
Si un modelo 3D tiene varias animaciones empaquetadas en él, un solo Animator component puede manejarlas todas.
En el ejemplo anterior, dos animaciones se manejan mediante distintos state objects, y luego ambas se asignan al mismo Animator component.
Cada bone en una animación solo puede verse afectado por una animación a la vez, a menos que estas animaciones tengan un weight que sume un valor de 1 o menos.
Si una animación solo afecta a las piernas de un personaje, y otra solo afecta a la cabeza de un personaje, entonces pueden reproducirse al mismo tiempo sin problema. Pero si ambas afectan a las piernas del personaje, entonces debes reproducir solo una a la vez, o reproducirlas con valores de weight weight más bajos.
Si en el ejemplo anterior, la bite animation solo afecta a la boca del shark, y la swim animation solo afecta a los bones de la columna del shark, entonces ambas pueden reproducirse al mismo tiempo.
📔 Nota: Animator.playSingleAnimation() detiene todas las demás animaciones que la Entity está reproduciendo actualmente. Para reproducir varias animaciones al mismo tiempo, modifica la playing propiedad en los estados de animación manualmente.
Velocidad de la animación
Cambia la velocidad a la que se reproduce una animación modificando la speed propiedad. El valor de speed es 1 por defecto.
Establece speed por debajo de 1 para reproducirla más despacio, por ejemplo 0.5 para reproducirla a la mitad de velocidad. Establécelo por encima de 1 para reproducirla más rápido, por ejemplo 2 para reproducirla al doble de velocidad.
Animation weight
El weight La propiedad permite que un solo modelo realice varias animaciones a la vez, calculando un promedio ponderado de todos los movimientos implicados en la animación. El valor de weight determina la importancia que se le dará a esa animación en el promedio.
Por defecto, weight es igual a 1. El valor de weight no puede ser mayor que 1.
El weight El valor de todas las animaciones activas en una Entity debería sumar 1 en todo momento. Si suma menos de 1, el promedio ponderado usará la posición predeterminada del armature para la parte restante del cálculo.
Por ejemplo, en el ejemplo de código anterior, estamos reproduciendo la swim animation, que solo tiene un weight de 0.2. Este movimiento de natación será bastante sutil: solo el 20% de la intensidad que define la animación. El 80% restante del cálculo toma valores de la postura predeterminada del armature.
El weight propiedad puede usarse de formas interesantes, por ejemplo la weight propiedad de swim podría establecerse en proporción a la velocidad a la que nada el shark, de modo que no necesitas crear varias animaciones para natación rápida y lenta.
También podrías cambiar el weight valor gradualmente al iniciar y detener una animación para darle una transición más natural y evitar saltos desde la pose predeterminada hasta la primera pose de la animación.
📔 Nota: El valor añadido de weight de todas las animaciones que actúan sobre un bone de un modelo 3D no puede ser mayor que 1. Si más de una animación está afectando a los mismos bones al mismo tiempo, deben tener su weight establecido en valores que sumen menos de 1.
Última actualización