Animaciones de FreeMinecraftModels
Esta página documenta lo que FreeMinecraftModels hace realmente con los datos de animación dentro de un archivo .bbmodel o .fmmodel: qué nombres son especiales, cómo se hornean los keyframes, qué modos de interpolación y de bucle se respetan, y cómo se controla la IK. Es intencionalmente conservadora: todo lo que aquí aparece es visible en el pipeline de importación y de runtime.
Para las reglas de nomenclatura de huesos y el resto del contrato de importación, consulta las Notas de Creación de Modelos.
Las Cinco Animaciones de Estado
FreeMinecraftModels vincula exactamente cinco nombres de animación en minúsculas a estados automáticos de runtime. Todo lo demás en el modelo es una animación personalizada.
| Nombre de la animación | En bucle | Cuándo se reproduce |
|---|---|---|
spawn | no | Una vez, al crear el modelo. Pasa a idle cuando termina |
idle | sí | Mientras la velocidad de la entidad subyacente sea igual o inferior a 0.08 |
walk | sí | Mientras la velocidad de la entidad subyacente sea superior a 0.08 |
attack | no | Cuando se activa; vuelve a idle cuando termina |
death | no | Con removeWithDeathAnimation() |
Reglas que se derivan de cómo está construida la máquina de estados:
- El estado inicial es
spawnsi el modelo lo tiene y, si no,idle. Un modelo que no tenga ninguno de los dos no tiene estado actual, por lo que no se anima nada hasta que algo se reproduzca explícitamente. - Solo las animaciones que existen en el modelo obtienen un estado. Un modelo con
walkpero sinidlenunca sale dewalkpor sí mismo. - El cambio idle/walk lee la velocidad de la entidad subyacente, así que en realidad es una característica de
DynamicEntity. Las entidades estáticas y los disfraces de jugador no tienen una entidad subyacente para este propósito y simplemente se quedan enidle; el armor stand que respalda a un prop no se mueve, así que los props también se quedan enidle. Los tres controlan sus animaciones reales mediante scripts, la API o (en el caso de los disfraces) el propio controlador de disfraces de FMM.
jump solo existe en el enumJUMP existe en el enum AnimationStateType, y el estado de caminar sí solicita una transición de salto cuando la entidad deja el suelo, pero nunca se registra ningún estado de salto, así que esa solicitud no resuelve a nada. Una animación llamada jump no está muerta: simplemente se comporta como cualquier otra animación personalizada y hay que activarla manualmente. Los disfraces de jugador son la excepción: usan un controlador aparte en el que jump sí está conectado.
Los Disfraces de Jugador Usan Otro Conjunto
Un disfraz de jugador no ejecuta la máquina de estados anterior. Tiene su propio controlador por tick con cinco nombres reservados — attack, jump, sneak, walk, idle — evaluados en ese orden de prioridad, y avisa en la consola si el modelo no tiene idle. Consulta Disfraces de Jugador para ver la tabla completa y la advertencia sobre el temporizado de las animaciones de un solo uso.
Animaciones Personalizadas
Cualquier animación cuyo nombre no sea uno de los cinco anteriores puede reproducirse igualmente por nombre:
modeledEntity.playAnimation("open", /* blend */ true, /* loop */ false);
modeledEntity.stopCurrentAnimations();
boolean exists = modeledEntity.hasAnimation("open");
context.prop:play_animation("open", true, false)
context.prop:stop_animation()
blendno hace una fusión progresiva.truepone la animación en cola para que empiece después de que se complete el tick del estado actual;falseinterrumpe y cambia de inmediato.loopsolo se aplica a las animaciones personalizadas. Un estado integrado usa su propia configuración de bucle sin importar lo que pases.- Cuando una animación personalizada sin bucle termina, la entidad vuelve al último estado integrado confirmado (lo que estuviera haciendo antes), o a
idlesi no había ninguno. playAnimationdevuelvefalsecuando el nombre no coincide ni con un estado registrado ni con una animación del modelo.stopCurrentAnimations()pasa aidlecuando el modelo tiene esa animación; en caso contrario sale del estado actual y deja el modelo sin ninguna animación activa.- Mientras se está reproduciendo una animación personalizada, una solicitud de
attack,attack_meleeoattack_rangedse descarta para que una secuencia scriptada no se vea interrumpida por el combate rutinario.
Temporizado y Duración
- Blockbench guarda la duración de la animación en segundos. FMM la convierte con
ceil(seconds x 20), así que la duración es siempre un número entero de ticks y las animaciones cortas se redondean hacia arriba en lugar de hacia abajo. - Cada animación se hornea en un array plano de frames por tick durante la importación. La reproducción es una consulta al array por tick, no una interpolación en vivo.
- Las animaciones en bucle se indexan con
counter % duration; las que no están en bucle se fijan al último frame y dejan de renderizar más cambios. - Los tiempos de los keyframes conservan su posición de tick fraccionaria (
20 x time, sin redondear), así que un keyframe en 0,37 s cae entre ticks y se interpola correctamente en lugar de ajustarse o descartarse. El keyframe final de una animación se conserva en lugar de recortarse por el redondeo. - Si dos keyframes del mismo canal caen exactamente en el mismo tiempo, gana el que aparece después en el orden del archivo.
- Un keyframe con un tiempo no finito aborta esa pista y produce un único aviso
Malformed animation timeline for model ...por animación, mientras que las demás animaciones del modelo se siguen convirtiendo.
Las Animaciones de Longitud Cero Son Válidas
Una animación cuya longitud sea 0 (o negativa) se trata como una pose estática intencionada: una decisión de creación habitual en muebles y otros props que necesitan una entrada llamada "sin animación". Se omite en silencio, sin aviso, y no aporta ningún frame.
Modos de Bucle
La configuración de bucle de Blockbench se lee directamente de la animación:
| Modo de bucle de Blockbench | Runtime de Java | Exportación a Bedrock |
|---|---|---|
loop | se repite indefinidamente | "loop": true |
once | se reproduce entera y se detiene | "loop": false |
hold | se reproduce entera y mantiene el último frame | "loop": "hold_on_last_frame" |
Tipos de Interpolación
Cada keyframe lleva su propio tipo de interpolación, y el segmento que entra hacia un keyframe usa el tipo de ese keyframe. Se admiten cuatro:
| Tipo de Blockbench | Comportamiento en FMM |
|---|---|
linear | Interpolación lineal directa |
catmullrom | Interpolación suavizada (ease in/out) |
bezier | Aproximada con puntos de control fijos de 0.42 / 0.58: FMM no lee los manejadores bezier de cada keyframe |
step | Salta al valor anterior hasta el siguiente keyframe |
Cualquier cosa fuera de ese conjunto no se puede analizar y se reporta como una timeline malformada.
Canales Animados
Se hornean tres canales por hueso: rotación, posición y escala. Notas que importan al crear modelos:
- Los valores de posición se dividen entre 16 (píxeles de Blockbench a bloques).
- Los valores de rotación se convierten a radianes.
- La
format_version5 de Blockbench y posteriores invierten el signo de la rotación X e Y y de la posición X. FMM lo compensa automáticamente según la versión de formato declarada, así que no lo corrijas a mano, pero tampoco mezcles una declaración v5 con datos con forma de v4. - Un hueso sin keyframes en un canal conserva su valor de reposo para ese canal; un hueso sin ningún frame para un tick dado se restablece a rotación
0,0,0, traslación0,0,0, escala1,1,1. - Los puntos de datos de los keyframes pueden estar escritos como cadenas de texto en el
.bbmodel. FMM los analiza como números simples: una cadena vacía se convierte en1para la escala y en0en los demás casos, y cualquier cosa que no se pueda analizar registraFailed to parse supposed number value ...y se convierte en0. Las expresiones Molang no se evalúan. - Solo se lee el primer punto de datos de un keyframe, así que los valores pre/post separados de Blockbench en un keyframe step se colapsan en uno solo.
Qué No Se Anima
- El hueso
hitbox. Las pistas de animación que lo tengan como objetivo se omiten directamente. - Las pistas de efectos de Blockbench (animadores de sonido, partículas e instrucciones de timeline). Se ignora cualquier animador cuyo tipo no sea
boneonull_object, así que FMM no disparará sonidos ni partículas desde una timeline de animación. Contrólalos en su lugar desde un script de Lua o desde tu propio plugin. - Los huesos que no se pudieron resolver por nombre. Una pista que apunte a un hueso inexistente registra
Failed to get bone <name> from model <model>!y se omite.
Cinemática Inversa (IK)
Los null objects de Blockbench actúan como controladores de IK. FMM resuelve las cadenas en runtime con FABRIK (Forward And Backward Reaching Inverse Kinematics), limitado a 10 iteraciones con una tolerancia de 0.001.
Cómo encaja todo:
- Un null object que tenga tanto
ik_source(hueso raíz de la cadena) comoik_target(hueso final o locator) define una cadena. La cadena se descubre recorriendo la jerarquía hacia arriba desde el objetivo hasta el origen. - Solo se leen los keyframes de posición del null object. Se convierten en un desplazamiento de objetivo por frame relativo a la posición de reposo del controlador; las pistas de rotación y escala de un null object se ignoran.
- En cada tick se aplica el desplazamiento de objetivo del frame actual y se resuelve la cadena. En un frame sin datos de IK, las rotaciones de IK de la cadena se limpian en su lugar.
lock_ik_target_rotationen el null object se lee desde el modelo.
Las cadenas que no se pueden resolver se omiten con un aviso de consola que las nombra; consulta las Notas de Creación de Modelos para ver los mensajes exactos y las restricciones de creación.
Exportación a Bedrock
Cada modelo convertido escribe además un archivo de animación de Bedrock en animations/<model_id>.animation.json dentro del bundle generado:
- Los identificadores de animación son
animation.fmm.<model_id>.<animation_name>, con los nombres saneados para Bedrock. animation_lengthes la duración en segundos, con un mínimo de0.05para que una animación de un solo tick siga siendo válida.- El modo de bucle se mapea como se muestra en la tabla de Modos de Bucle.
- Un modelo sin animaciones sigue recibiendo una única entrada
idlesin efecto para que la definición de entidad de Bedrock siga siendo válida. - Solo se exportan los huesos visuales.
hitbox, los huesos de nametagfmm_nametag_bone_*autogenerados y los huesos de punto de montajem_quedan excluidos de la geometría y, por tanto, del bloque de huesos de animación. El huesotag_que tú creas no se excluye: se exporta como cualquier otro hueso (normalmente como uno vacío, sin cubos); solo se filtra su hueso de nametag generado. - Se genera un controlador de animación por animación, conmutado por una propiedad de entidad, que es la forma en que FMM reproduce una animación concreta en un cliente de Bedrock.
Consulta Salida del Resource Pack para saber dónde acaba el bundle en el disco.
Reproducir Animaciones Desde Otros Sistemas
| Quien llama | Punto de entrada |
|---|---|
| Plugin (Java) | ModeledEntity#playAnimation(String, boolean blend, boolean loop) / #stopCurrentAnimations() / #hasAnimation(String) |
| Script de Lua de un prop | context.prop:play_animation(name, blend, loop) / context.prop:stop_animation() |
| Cualquier tabla de entidad de Lua | entity.model:play_animation(name, blend, loop) / entity.model:stop_animations() (disponible cuando entity.is_modeled es true) |
Consulta la Guía de API y Desarrollo y Lua: API de Props e Ítems para conocer las superficies relacionadas.
Solución de Problemas
Mi animación nunca se reproduce automáticamente.
Solo spawn, idle, walk, attack y death se disparan por sí solas. Todo lo demás necesita una llamada explícita a playAnimation / play_animation.
Mi modelo no hace absolutamente nada.
Lo más probable es que no tenga ni una animación spawn ni una idle, así que no se entra en ningún estado al crearlo. Añade un idle.
Mi animación se reproduce pero nada se mueve. Revisa la duración de la animación. Una animación de longitud cero se trata como una pose estática y se omite en silencio por diseño.
Las rotaciones salen invertidas.
Revisa meta.format_version en el .bbmodel. FMM invierte el signo de la rotación X/Y para la versión de formato 5 y posteriores; un archivo que declare una versión pero contenga los datos de la otra saldrá invertido.
La consola dice Malformed animation timeline for model ....
Una pista de esa animación no se pudo leer o interpolar. El aviso se dispara una vez por animación y nombra el hueso o el controlador de IK implicado; las demás animaciones del modelo se siguen convirtiendo.
Los sonidos y las partículas de mi timeline de Blockbench no hacen nada. Las pistas de efectos no se importan. Actívalos desde un script de Lua o desde tu propio plugin.