Animações do FreeMinecraftModels
O FreeMinecraftModels importa animações de ficheiros .bbmodel e .fmmodel. Esta página descreve os nomes reservados, os tempos dos fotogramas, a interpolação, os modos de repetição e a cinemática inversa (IK).
Para as regras dos nomes dos ossos e os restantes requisitos de importação, consulte Notas sobre criação de modelos.
As cinco animações de estado
O FreeMinecraftModels associa exatamente cinco nomes de animação em minúsculas a estados automáticos. As restantes animações do modelo são personalizadas.
| Nome da animação | Repete | Quando é reproduzida |
|---|---|---|
spawn | Não | Uma vez, ao criar o modelo. Passa para idle ao terminar |
idle | Sim | Sem movimento horizontal; passa para walk quando a velocidade em X ou Z deixa de ser zero |
walk | Sim | Durante o movimento horizontal; passa para idle quando a entidade está no chão e as velocidades X e Z são ambas zero |
attack | Não | Quando ativada; regressa a idle ao terminar |
death | Não | Ao chamar removeWithDeathAnimation() |
Da organização da máquina de estados resultam estas regras:
- O estado inicial é
spawn, se existir, ouidle. Um modelo sem ambos fica sem estado atual e só anima quando algo o solicita explicitamente. - Só as animações existentes recebem um estado. Um modelo com
walk, mas semidle, nunca sai sozinho dewalk. - A alternância entre
idleewalkusa a velocidade horizontal da entidade subjacente. O movimento apenas vertical não inicia a caminhada. As entidades estáticas e os disfarces não têm uma entidade subjacente para este efeito, e os elementos decorativos parados não têm movimento horizontal. As suas animações adicionais são controladas por scripts, pela API ou pelo controlador de disfarces do FMM.
jump existe apenas no enumJUMP existe no enum AnimationStateType, e o estado de caminhada solicita uma transição para salto quando a entidade deixa o chão. Contudo, não é registado nenhum estado de salto, pelo que o pedido não tem efeito. Uma animação chamada jump continua a poder ser usada como animação personalizada, acionada manualmente. Os disfarces de jogadores usam um controlador separado no qual jump está implementado.
Os disfarces usam outro conjunto
Um disfarce de jogador acrescenta um controlador por tick que pede animações ao mesmo motor de reprodução. Os seus cinco nomes reservados são attack, jump, sneak, walk e idle, avaliados por essa ordem quando a contagem decrescente de uma animação de execução única está inativa. É registado um aviso na consola se faltar idle. Consulte Disfarces de jogadores para ver a tabela completa e a limitação de duração dessas animações.
Animações personalizadas
As animações com outros nomes podem ser reproduzidas explicitamente:
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()
blendnão faz uma transição gradual entre animações. Comtrue, coloca a animação em espera até terminar o tick do estado atual. Comfalse, interrompe-o e muda imediatamente.- Só existe uma posição em espera; um novo pedido em espera substitui o anterior. Uma animação personalizada começa imediatamente se não houver estado atual. Um estado integrado em espera não consegue avançar a partir de um estado atual nulo; nesse caso, use
blend=false. loopaplica-se apenas a animações personalizadas. Um estado integrado usa a sua própria regra de repetição, independentemente do argumento.- Use os nomes exatos nas animações personalizadas e em
hasAnimation: ambas as pesquisas distinguem maiúsculas de minúsculas. Os pedidos de reprodução de estados integrados aceitam outras combinações, mas o registo do estado continua a exigir o nome em minúsculas no modelo. - Quando uma animação personalizada sem repetição termina, pede o regresso ao último estado integrado confirmado guardado, ou a
idlese não houver nenhum. Esse é o último estado integrado de que o gestor saiu anteriormente, que pode ser diferente do estado ativo imediatamente antes da animação personalizada. Se o estado pedido não existir, o estado personalizado permanece selecionado, sem novas atualizações de fotogramas. playAnimationdevolvefalsepara nomes desconhecidos, exceto nos pedidos de ataque suprimidos descritos abaixo. Um resultado positivo significa que o pedido foi aceite, não que já tenha sido apresentado um fotograma visível.stopCurrentAnimations()passa paraidle, se existir. Caso contrário, sai do estado atual e deixa o modelo sem animação ativa.- Durante uma animação personalizada, os pedidos de
attack,attack_meleeeattack_rangedsão ignorados, evitando que o combate normal interrompa uma sequência controlada por script. - A morte é terminal na máquina de estados partilhada: novos pedidos devolvem
false, as transições em espera são descartadas e parar animações não altera esse estado. O método público de paragem também envia um pedido separado de paragem ao Bedrock; não o use para gerir uma sequência de morte nos dois clientes.
Tempo e duração
- O Blockbench guarda a duração em segundos. O FMM converte-a com
ceil(seconds x 20): a duração é sempre um número inteiro de ticks, arredondado para cima. - Na importação, cada animação é convertida num vetor de fotogramas, um por tick. A reprodução consulta esse vetor; não calcula a interpolação em tempo real.
- As animações em repetição usam o índice
counter % duration. As restantes ficam no último fotograma e deixam de apresentar alterações. - Os tempos dos fotogramas-chave mantêm a posição fracionária em ticks (
20 x time, sem arredondamento), pelo que um fotograma-chave aos 0,37 segundos contribui para a interpolação entre ticks. Os fotogramas são amostrados em ticks inteiros de0aduration - 1. Um fotograma-chave exatamente no fim declarado influencia a interpolação, mas não é amostrado diretamente. Coloque a pose final antes desse limite se um fotograma apresentado tiver de a atingir. - Se dois fotogramas-chave do mesmo canal tiverem exatamente o mesmo tempo, prevalece o que aparece mais tarde no ficheiro.
- Um tempo não finito interrompe essa pista e produz um único aviso
Malformed animation timeline for model ...por animação. As outras animações do modelo continuam a ser convertidas.
Animações de duração zero são válidas
Uma animação de duração 0 ou negativa é tratada como uma pose estática intencional. É comum em mobília e outros elementos decorativos que precisam de uma entrada com nome para representar a ausência de animação. É ignorada sem aviso e não fornece fotogramas.
Modos de repetição
A opção de repetição do Blockbench controla a animação exportada para Bedrock:
| Modo do Blockbench | Exportação Bedrock |
|---|---|
loop | "loop": true |
once | "loop": false |
hold | "loop": "hold_on_last_frame" |
Em Java, a reprodução usa a regra do estado integrado ou o argumento loop da animação personalizada. Não escolhe a repetição a partir deste campo do Blockbench. Assim, Java e Bedrock podem reproduzir de forma diferente quando as opções não coincidem.
Tipos de interpolação
Cada fotograma-chave tem um tipo de interpolação, aplicado ao segmento que chega até ele. São suportados quatro tipos:
| Tipo do Blockbench | Comportamento no FMM |
|---|---|
linear | Interpolação linear direta |
catmullrom | Interpolação suavizada, com aceleração e desaceleração |
bezier | Aproximação com pontos de controlo fixos 0.42 / 0.58; o FMM não lê os controlos Bézier individuais |
step | Mantém o valor anterior até ao fotograma-chave seguinte |
Qualquer outro tipo falha na leitura e é comunicado como uma linha temporal inválida.
Canais animados
São preparados três canais por osso: rotação, posição e escala. Ao criar animações, tenha em conta que:
- Os valores de posição são divididos por 16, convertendo píxeis do Blockbench em blocos.
- Os valores de rotação são convertidos em radianos.
- O
format_version5 e posteriores do Blockbench inverte o sinal das rotações X e Y e da posição X. O FMM compensa automaticamente de acordo com a versão declarada. Não faça uma correção manual nem declare v5 para dados com a convenção v4. - Um osso sem fotogramas-chave num canal mantém o valor de repouso desse canal. Um osso sem qualquer fotograma para um tick é reposto para rotação
0,0,0, translação0,0,0e escala1,1,1. - Os pontos de dados podem aparecer como cadeias de texto no
.bbmodel. O FMM interpreta-os como números simples: uma cadeia vazia passa a1na escala e a0nos restantes canais. Um valor ilegível geraFailed to parse supposed number value ...e passa a0. As expressões Molang não são avaliadas. - Só é lido o primeiro ponto de dados de cada fotograma-chave. Os valores separados de antes e depois de um fotograma
stepdo Blockbench ficam, por isso, reduzidos a um único valor.
O que não é animado
- O osso
hitbox: as pistas dirigidas a ele são ignoradas. - Os fotogramas-chave de som e de instruções da linha temporal nas pistas de efeitos do Blockbench. O FMM importa apenas os fotogramas-chave de partículas de uma pista de efeitos; consulte Partículas. Para produzir sons, use um script Lua ou o seu próprio plugin.
- Ossos que não foram encontrados pelo nome. Uma pista dirigida a um osso inexistente gera
Failed to get bone <name> from model <model>!e é ignorada.
Cinemática inversa (IK)
Os objetos nulos do Blockbench funcionam como controladores de IK. O FMM resolve as cadeias durante a execução com FABRIK (Forward And Backward Reaching Inverse Kinematics), limitado a 10 iterações e com tolerância 0.001.
O funcionamento é o seguinte:
- Um objeto nulo com
ik_source, o osso raiz, eik_target, o osso final ou localizador, define uma cadeia. A deteção consulta a hierarquia e também permite pesquisas entre irmãos e nos descendentes; alvos irmãos no nível raiz produzem uma cadeia apenas com o osso de origem. - Só os fotogramas-chave de posição do objeto nulo controlam a IK. Tornam-se um deslocamento por fotograma somado à posição de repouso do osso ou localizador alvo. O solucionador não usa a posição de repouso guardada do controlador como base do objetivo. A rotação e a escala não controlam a IK.
- A cada tick, as cadeias IK associadas à animação atual recebem os deslocamentos e são resolvidas. Uma cadeia associada sem dados para esse fotograma é limpa. Cada mudança de animação, bem como
stopCurrentAnimations(), limpa as rotações IK de todas as cadeias, pelo que uma pose IK não passa para a animação seguinte. lock_ik_target_rotationé lido e guardado, mas o solucionador atual não o aplica.
As cadeias que não puderem ser resolvidas são ignoradas, com um aviso identificável na consola. Consulte Notas sobre criação de modelos para as mensagens exatas e os requisitos de criação.
Exportação Bedrock
Cada modelo convertido escreve também um ficheiro Bedrock em animations/<model_id>.animation.json, dentro do conjunto de recursos gerado:
- Os identificadores seguem
animation.fmm.<model_id>.a_<hex>, em que<hex>são os bytes UTF-8 do nome da animação escritos em hexadecimal. Assim, dois nomes que só diferem em carateres que o Bedrock não permite recebem identificadores distintos. animation_lengthé a duração em segundos, com um mínimo de0.05, permitindo animações válidas de um tick.- O modo de repetição segue a tabela Modos de repetição.
- Um modelo sem animações recebe uma entrada
idlesem efeito, para manter válida a definição da entidade Bedrock. - A geometria exclui
hitbox, os ossos de etiquetas de nome geradosfmm_nametag_bone_*e os pontos de montadam_; mantém as âncorastag_criadas pelo autor. O exportador de animações escreve as pistas pré-calculadas sem aplicar esse mesmo filtro de ossos visuais. Não anime ossos de montada excluídos esperando ver a sua geometria. - A exportação Bedrock usa fotogramas pré-calculados de rotação, posição e escala dos ossos. Não incorpora nessas pistas as rotações produzidas pelo solucionador IK durante a execução; verifique separadamente no Bedrock os modelos que dependam de IK.
- É gerado um controlador por animação, selecionado por uma propriedade da entidade. É assim que o FMM reproduz uma animação específica num cliente Bedrock.
- Os fotogramas-chave de partículas passam a constituir a linha temporal
particle_effectsda animação, pelo que os clientes Bedrock os reproduzem nativamente. Consulte Partículas.
Consulte Pacote de recursos gerado para saber onde os ficheiros ficam no disco.
Reproduzir animações a partir de outros sistemas
| Origem | Ponto de entrada |
|---|---|
| Plugin Java | ModeledEntity#playAnimation(String, boolean blend, boolean loop) / #stopCurrentAnimations() / #hasAnimation(String) |
| Script Lua de elemento decorativo | context.prop:play_animation(name, blend, loop) / context.prop:stop_animation() |
| Qualquer tabela Lua de entidade | entity.model:play_animation(name, blend, loop) / entity.model:stop_animations(); disponível quando entity.is_modeled é true |
Consulte o Guia da API e desenvolvimento e a API Lua de elementos decorativos para conhecer as operações relacionadas.
Os valores predefinidos de Lua diferem: context.prop:play_animation(name) usa blend=true, loop=true, enquanto entity.model:play_animation(name) usa false, false. Passe ambos os booleanos explicitamente quando a diferença for relevante.
Resolução de problemas
A animação nunca é reproduzida automaticamente.
A máquina de estados partilhada reconhece spawn, idle, walk, attack e death em minúsculas. O movimento controla as transições idle/walk; os ataques e a morte continuam a precisar do seu acionamento durante a execução. Os restantes nomes exigem uma chamada explícita a playAnimation / play_animation, exceto os nomes adicionais escolhidos pelo controlador de disfarces.
O modelo não faz nada.
Provavelmente não tem spawn nem idle, pelo que não entra num estado ao ser criado. Adicione idle.
A animação é reproduzida, mas nada se move. Verifique a duração. Uma animação de duração zero é tratada como pose estática e ignorada sem aviso.
As rotações estão espelhadas.
Verifique meta.format_version no .bbmodel. O FMM inverte o sinal das rotações X/Y para a versão de formato 5 e posteriores. Um ficheiro que declare uma versão, mas contenha dados da outra convenção, fica espelhado.
A consola apresenta Malformed animation timeline for model ....
Uma pista dessa animação não pôde ser lida ou interpolada. O aviso surge uma vez por animação e identifica o osso ou controlador IK. As restantes animações continuam a ser convertidas.
Os sons da linha temporal do Blockbench não funcionam. Os fotogramas-chave de som não são importados. Produza os sons através de um script Lua ou do seu próprio plugin. Os fotogramas-chave de partículas são importados; se não aparecerem, consulte Partículas.