Animação Roblox (R6 / R15)
Você cria um movimento como uma pequena especificação de movimento em JSON: um punhado de poses-chave escritas em termos anatômicos ("braço direito 90° para frente", "joelho dobrado 60°"). O motor integrado faz tudo que é propenso a erros manualmente: matemática de juntas Roblox para ambas as rigs, interpolação, manutenção dos pés no chão, um visualizador 3D, avisos de sanidade e a exportação de keyframes horneados.
O usuário julga o resultado assistindo, então o ciclo é: planejar as fases → escrever a especificação → compilar → olhar o storyboard você mesmo → corrigir → entregar pré-visualização + keyframes. Não pule a etapa de olhar; números de pose que parecem certos no papel muitas vezes estão visivelmente errados (um braço atravessando o peito, um chute que nunca atinge a bola).
Fluxo de trabalho
- Defina o movimento. Rig (R6 ou R15; pergunte apenas se realmente não puder ser inferido, caso contrário, use R15 como padrão e avise), dominância, looping ou one-shot, duração aproximada e quais ganchos de jogabilidade são necessários (quadro de acerto, lançamento de bola, passos). Comece a construir imediatamente para um pedido claro.
- Divida em fases antes de escrever números. Quase toda ação é: prontidão → antecipação → ação → acompanhamento → recuperação. Leia
references/motion-cookbook.mdpara o gênero que você está fazendo (combate, esportes, loops de locomoção, acrobacias, especificidades do R6); ele tem tabelas de tempo e receitas de pose. - Escreva a especificação para
<nome>.json. Comece do arquivo mais próximo emexamples/em vez de começar do zero. - Compile:
node <skill>/scripts/ranim.cjs <nome>.json --out out(várias especificações podem ser passadas; elas se tornam abas em uma pré-visualização). Precisa apenas de Node, sem pacotes. - Leia o relatório impresso no stdout. Ele lista onde a cabeça, mãos e pés realmente estão em cada key (studs: R = à direita do personagem, U = acima do chão, F = na frente) e imprime linhas
WARN. Use as posições para verificar a intenção: o punho está realmente na frente do peito, o pé está na altura da bola? - Olhe
out/storyboard-<Nome>.pngcom a ferramenta de Leitura (cada key de uma vista 3/4 e uma vista lateral). Se nenhum PNG foi produzido, tire um screenshot deout/preview.htmlcom um navegador headless ou leia o SVG. Compare cada painel com a fase que você pretendia. - Corrija e recompile até que as poses sejam claramente legíveis e os avisos tenham desaparecido ou sejam conscientemente aceitos. Duas ou três rodadas é normal.
- Entregue: o
out/preview.htmlinterativo (publique como artefato ou envie o arquivo), maisout/<Nome>.rbxmxeout/<Nome>.lua. Mostre a imagem do storyboard inline se puder. Diga ao usuário brevemente como colocar no Studio (abaixo) e quais eventos de animação existem.
Especificação do movimento
{
"name": "JabCross", // torna-se o nome do KeyframeSequence e do arquivo
"title": "Combo jab-cross", // mostrado no visualizador
"rig": "R15", // "R15" ou "R6"
"priority": "Action", // Idle | Movement | Action | Action2..4 | Core
"loop": false,
"description": "Uma ou duas frases mostradas ao lado da pré-visualização.",
"keys": [
{ "t": 0, "label": "guarda", "note": "Mostrado na lista de fases.",
"pose": { "UpperTorso": { "turnR": 10, "bendFwd": 8 },
"LeftUpperArm": { "fwd": 50, "out": 8 }, "LeftLowerArm": { "bend": 120 },
"LeftFoot": "flat" } },
{ "t": 0.1, "label": "jab", "ease": "out", "copy": "guarda",
"pose": { "LeftUpperArm": { "fwd": 86, "in": 22 }, "LeftLowerArm": { "bend": 6 } } },
{ "t": 0.8, "label": "recupera", "copy": "guarda" }
],
"markers": [ { "t": 0.1, "name": "Hit", "value": "jab" } ],
"props": [ { "type": "ball", "radius": 0.6, "color": "#e07a2c", "keys": [ ... ] } ]
}
(Comentários são apenas para explicação; o arquivo deve ser JSON puro.)
Campos opcionais de nível superior: fps (padrão 30; use 60 para movimentos muito rápidos), duration (padrão para a última key), grounding ("off" para controlar a altura manualmente), mirror: true (inverte todo o clipe esquerda/direita, por exemplo, uma versão para o pé esquerdo), endKeyframe: true.
Keys
tsegundos (ajustado para um quadro). A primeira key está em 0.posemapeia nome da junta → canais em graus. Uma junta omitida de uma key é simplesmente interpolada através dessa key, então keys intermediárias podem mencionar apenas as juntas que importam. Uma junta nunca mencionada permanece em repouso e não é exportada; uma mencionada pela primeira vez após a key 0 começa a partir do repouso (0°).copy: o rótulo ou índice de uma key anterior. A pose começa como uma cópia eposesubstitui partes dela."mirror": truecomcopytroca esquerda e direita, que é como ciclos de caminhada/corrida são feitos a partir de meia passada.easemodela o segmento saindo desta key:smooth(padrão, suaviza naturalmente sem overshoot),linear,in(começa devagar, termina rápido: preparações liberando em um golpe),out(começa rápido, estabiliza: impactos),inOut,hold,overshoot,anticipate,bounce,elastic.lift: altura em studs do ponto mais baixo do corpo acima do chão nesta key (padrão 0). É assim que pulos são feitos; veja Grounding.
Juntas e canais
Os ângulos são anatômicos e a mesma palavra significa a mesma coisa em ambos os lados do corpo, então uma pose espelhada não precisa de mudanças de sinal. Cada canal tem um alias de direção oposta; use o que parecer mais natural.
| Juntas | Canais (alias para a direção oposta) |
|---|---|
Raiz: LowerTorso (R15), Torso (R6) | bendFwd (bendBack), turnL (turnR), leanR (leanL), moveFwd (moveBack), moveR (moveL), moveUp (moveDown) em studs |
Coluna: UpperTorso, Head | bendFwd (bendBack), turnL (turnR), leanR (leanL) |
Membros superiores: Left/RightUpperArm, Left/RightUpperLeg; R6 Left Arm, Right Arm, Left Leg, Right Leg | fwd (back) balança o membro para frente/cima, out (in) para longe do / através do corpo, twistOut (twistIn) gira ao longo do seu próprio comprimento |
Left/RightLowerArm, Left/RightLowerLeg | bend: cotovelos e joelhos em sua direção natural (0 = esticado) |
Left/RightHand, Left/RightFoot | fwd (back), out (in), twistOut (twistIn). Pés também aceitam a string "flat" |
Marcos: braço fwd: 90 aponta reto para frente, fwd: 180 reto para cima, out: 90 é uma pose de T. Perna fwd: 90 é um chute frontal na altura da cintura. As rotações são compostas de pai para filho, então a virada do peito carrega os braços com ela; vire a Head na direção oposta para manter os olhos no alvo.
R6 tem seis partes e sem cotovelos, joelhos, mãos ou pés, então a silhueta vem dos ângulos do torso e dos membros inteiros; exagere um pouco. Os nomes dos membros R6 contêm um espaço ("Right Arm").
Grounding
Por padrão, o motor abaixa ou levanta a raiz a cada quadro para que o ponto mais baixo do corpo fique exatamente lift studs acima do chão. Consequências:
- Agachamentos, estocadas e aberturas de perna automaticamente abaixam os quadris; nunca ajuste manualmente a altura do quadril para uma pose em pé.
"flat"em um pé R15 resolve o tornozelo para que a sola fique plana independentemente do que a perna está fazendo. Use-o para cada pé plantado; dê ângulos explícitos ("back": 40= pontas dos pés) para pés no ar ou na ponta dos pés.- Um pulo são valores de
liftnas keys aéreas (pequeno na decolagem, maior no ápice, 0 no pouso). A rotação do corpo no ar vai na raiz: um backflip é obendBackda raiz variando 0 → 360 através das keys (os ângulos são contínuos, então 360 é uma volta completa, não "de volta a 0"). moveUpna raiz é ignorado enquanto o grounding está ativo. Defina"grounding": "off"apenas para coisas como natação ou escalada onde o chão é irrelevante.- Saltos e dashes no jogo são normalmente movidos pelo controlador de personagem, não pela animação. Para uma animação destinada a tocar durante um pulo de jogabilidade, pose o corpo e deixe
liftem 0. UseliftemoveFwdpara emotes autocontidos, ataques com um pulo e flips. Se o clipe terminar deslocado de onde começou, o relatório avisa, porque o Roblox faz o corpo voltar ao lugar quando a faixa para.
Marcadores e props
markersse tornamKeyframeMarkers, lidos no jogo comtrack:GetMarkerReachedSignal("Hit"). Coloque um em cada quadro que a jogabilidade se importa: janelas de acerto, contato ou lançamento de bola, passos, dicas sonoras.propssão apenas para pré-visualização (não são exportados) e existem para que o movimento possa ser julgado contra a coisa com a qual interage.type: "ball"comradius, ou qualquer outro tipo para uma caixa comsize: [x, y, z](uma espada é uma caixa longa e fina).até ou um nome de parte (o prop segue aquela parte;offset: [right, up, fwd]nos eixos da própria parte) ou um ponto fixo[right, up, fwd]em studs do ponto do chão sob o personagem. Com váriaskeyso prop se move entre âncoras;arcadiciona uma elevação parabólica ao segmento que sai daquela key (um arremesso ou passe). Vejaexamples/jump_shot.jsoneexamples/soccer_kick.json.
O que é bom
- Silhuetas legíveis. No storyboard, cada key deve ser reconhecível apenas pelo seu contorno. Se duas keys vizinhas parecem iguais, uma delas não está fazendo nenhum trabalho.
- Contraste no tempo. Antecipação lenta, ação muito rápida (2 a 4 quadros), uma pequena pausa no acompanhamento, recuperação mais lenta. Espaçamento uniforme entre as keys é a razão mais comum para um movimento parecer sem peso.
- O corpo inteiro participa. A potência começa nos pés e quadris, depois peito, depois ombro, depois mão ou pé. Dê aos quadris e peito uma contra-rotação na preparação e deixe o braço distante equilibrar o próximo.
- Pés permanecem no lugar. Um pé plantado mantém seus números R e F no relatório de key para key. Se ele precisar se mover, levante-o em uma key intermediária (um passo).
- Zero avisos, ou uma razão para cada um que você mantiver. Os limites são as amplitudes naturais das juntas; excedê-los geralmente significa que um canal diferente foi pretendido.
Colocando no Roblox Studio
Dê ao usuário ambas as rotas e os nomes dos eventos.
- Barra de comandos (mais rápido): selecione a rig no Explorer, abra View → Command Bar, cole todo o conteúdo de
<Nome>.lua, pressione Enter. O KeyframeSequence aparece noAnimSavesda rig (ou em ServerStorage se nada estiver selecionado), de onde o Animation Editor pode carregá-lo para ajustes. - Arquivo: arraste
<Nome>.rbxmxpara a viewport do Studio, ou clique com o botão direito em um serviço → Insert from File. - Publicação: para reproduzi-lo em um jogo ao vivo, ele deve ser enviado: abra-o no Animation Editor e publique, ou clique com o botão direito no KeyframeSequence → Save to Roblox, então use o ID de asset resultante em um objeto
AnimationeAnimator:LoadAnimation. Para testes locais rápidos no Studio,game:GetService("KeyframeSequenceProvider"):RegisterKeyframeSequence(seq)retorna um ID temporário. Os menus do Studio mudam de tempos em tempos; se uma etapa não corresponder ao que o usuário vê, diga isso e procure a redação atual em vez de insistir.
A exportação é horneada: um keyframe por quadro com easing linear, então o Studio reproduz exatamente o que a pré-visualização mostra em qualquer rig daquele tipo. Apenas as juntas que a especificação anima são escritas, então uma animação apenas da parte superior do corpo deixa as pernas livres para a caminhada padrão. A saída R15 carrega AuthoredHipHeight para que se retargetize para avatares de outras proporções.
Arquivos
scripts/ranim.cjs— motor, visualizador e exportador em um arquivo. Também utilizável como módulo:const R = require('.../ranim.cjs'); const c = R.compile(spec); R.report(c); R.sample(c, t).scripts/selftest.cjs— verifica a matemática das juntas contra a fórmula Motor6D do Roblox. Execute-o após editar o motor.examples/—soccer_kick,jump_shot(esportes com props de bola),jab_cross(combate R15),r6_sword_slash(combate R6 com arma),backflip(rotação de corpo inteiro e um pulo),r6_run(loop espelhado).references/motion-cookbook.md— tabelas de tempo e receitas de pose por gênero. Leia a seção relevante antes de criar.