Animação no Roblox: do rig vazio ao script que faz ela tocar no jogo
Animar no Roblox são duas coisas em dois lugares: desenhar o movimento no Animation Editor e mandar ele tocar por script. Este guia percorre as duas, com o detalhe do Add Keyframe Here que estraga timeline e o caso do rig sem Humanoid.
Produzido com IA a partir das fontes citadas abaixo, e conferido por checagens automáticas contra essas mesmas fontes. Nenhuma pessoa leu este texto antes da publicação. Política Editorial

Você desenhou a animação no Studio, ela roda bonita no editor, e no jogo publicado o personagem continua parado. É nesse ponto que a maior parte das pessoas desiste de animação no Roblox — e quase nunca o problema está na animação.
Animar no Roblox são duas coisas separadas, feitas em dois lugares diferentes: desenhar o movimento no Animation Editor, e mandar o movimento tocar por script. A documentação oficial trata as duas em páginas distintas, e é exatamente essa fronteira que engole o iniciante. Este guia percorre o caminho inteiro: do rig vazio até o script que faz a animação acontecer no servidor.
O problema
O primeiro obstáculo aparece antes de qualquer animação: só dá para criar animação em cima de um rig. Não é uma preferência do editor, é a condição de entrada — a documentação diz que você só consegue criar animações usando rigs, e uma Part solta na workspace não serve.
Um rig, na definição oficial, é um objeto com seções individuais ligadas por juntas. Quem ainda não tem um no lugar pode inserir um pronto com o Rig Generator, que já vem com as partes e os mecanismos básicos de um personagem. Isso resolve o primeiro travamento em trinta segundos, e é por onde vale começar mesmo que o objetivo final seja animar uma porta.
O segundo obstáculo é conceitual e custa mais caro. O Animation Editor serve para desenhar e publicar animações próprias em rigs — publicar, aqui, quer dizer virar um asset com id. Ele não liga a animação ao jogo. Depois de criada, a animação precisa de script para entrar em campo: a documentação é explícita ao dizer que você precisa usar scripts para incluir a animação no seu jogo. Quem espera que o personagem comece a se mexer só porque a animação existe está esperando por uma coisa que o Roblox nunca prometeu.
E existe uma terceira coisa, que só morde depois: a linha do tempo tem uma unidade própria. A animação roda a 30 quadros por segundo, e a régua mostra segundos e quadros — 0:15 é meio segundo, não quinze segundos. A janela abre exibindo a duração de um segundo, o que é pouco para quase tudo; ampliar a linha do tempo é a primeira coisa que se faz, e não a última.
Passo a passo
1. Ponha um rig na workspace. Se você não tem, use o Rig Generator. Se tem, selecione-o no viewport ou no Explorer antes de abrir o editor — sem seleção, o editor não tem em quem trabalhar.
2. Reconheça as três áreas da janela. O editor se divide em controles de reprodução, lista de faixas e linha do tempo. O indicador de posição mostra onde o scrubber está, em segundos e quadros. Vale gastar um minuto aqui: quase todo erro de timeline vem de não saber qual dessas três áreas está sendo clicada.
3. Crie as poses. Uma animação é feita de poses — e pose, na definição oficial, é a posição e a orientação de objetos Bone ou MeshPart dentro do rig. Na prática: expanda o rig no Explorer, selecione o osso ou a malha (mão, pé, torso), leve o scrubber até o quadro onde a pose deve existir, e mova ou gire.
Um detalhe que economiza muito tempo: dá para alternar entre mover e girar apertando R. Os dois modos funcionam como no resto do Studio, com os mesmos ajustes de snap da barra de ferramentas.
A cada ajuste, aparece uma faixa nova na lista e um keyframe novo na linha do tempo, naquele osso e naquele quadro. Esse é o sinal de que a pose foi registrada — se a faixa não apareceu, o movimento não entrou.
4. Veja rodar. Antes de refinar qualquer coisa, aperte a barra de espaço. Com duas poses — digamos, a cabeça olhando para a frente e depois virada para o lado — o editor já interpola o meio do caminho sozinho.
5. Refine os keyframes. É aqui que a animação deixa de parecer rascunho: ajustar keyframe um a um melhora bastante o resultado final. As operações que importam são quatro: inserir (menu de contexto, Add Keyframe Here), mover (arrastar para outra posição de tempo), duplicar (copiar e colar com o scrubber no destino) e apagar (selecionar e apertar Delete ou Backspace). Keyframe selecionado fica com borda azul — essa borda é a confirmação de que a operação seguinte vai cair no lugar certo.
6. Escolha o easing. Por padrão a peça vai de um keyframe ao outro em movimento uniforme, o easing linear. É o que faz animação de iniciante parecer robô. A documentação lista cinco estilos, e vale saber o que cada um faz antes de sair testando:
- Linear — velocidade constante.
- Constant — remove a interpolação entre o keyframe selecionado e o próximo; a animação salta de pose em pose.
- CubicV2 — entra e sai com interpolação cúbica. É o que a própria documentação usa para mostrar movimento natural.
- Elastic — move como se o objeto estivesse preso a um elástico.
- Bounce — move como se o começo ou o fim fosse quicante.
A direção do easing é a outra metade: ela define qual ponta do movimento recebe o efeito. Por padrão, o movimento sai mais lento no começo e mais rápido no fim. Trocar a direção é o ajuste que resolve movimento que "chega errado" sem que se saiba dizer por quê.
7. Publique e pegue o id. A animação vira asset, e é o id dela que o script vai usar.
8. Escreva o script. O padrão oficial para personagem tem quatro passos: garantir que o Humanoid tem um Animator, criar uma instância Animation com o AnimationId certo, carregar pelo Animator:LoadAnimation() — que devolve um AnimationTrack — e tocar com o Play() do track.
Para rig que não tem Humanoid — porta, alavanca, bicho, veículo — o caminho muda: é preciso criar um AnimationController com um Animator filho. Sem isso não existe onde carregar a faixa, e o script falha calado.
Artefato
O módulo abaixo resolve os dois casos no mesmo lugar e guarda a faixa carregada em cache, em vez de recarregar a cada uso. Ele também se desfaz do cache quando o rig sai do jogo — um vazamento discreto que só aparece depois de algumas horas de servidor cheio.
Troque o id pelo da sua animação. O GetMarkerReachedSignal no fim só dispara se a animação tiver um marcador com aquele nome: ele existe para detectar quando um evento nomeado da animação acontece, e é como se sincroniza som, dano ou efeito com o quadro exato do movimento.
Erro comum
O erro que mais estraga timeline está numa linha da documentação que quase ninguém lê: o keyframe entra na posição de tempo mais próxima de onde se clicou, e não onde está o scrubber.
A cabeça de quem está animando funciona ao contrário disso. Você leva o scrubber até 0:20 com cuidado, clica com o botão direito num ponto qualquer da faixa para abrir o menu, escolhe Add Keyframe Here — e o keyframe nasce onde o cursor estava, não em 0:20. A pose seguinte entra desalinhada, o movimento fica torto, e como a diferença costuma ser de poucos quadros, ninguém desconfia do clique: desconfia do próprio olho.
A correção é chata e infalível: clique com o botão direito exatamente sobre a posição de tempo onde o keyframe deve nascer. E confira na régua antes de seguir — corrigir um keyframe fora de lugar é arrastar; corrigir dez é refazer.
O segundo erro comum é o rig sem Humanoid. O script copiado de um tutorial de personagem procura o Humanoid, não acha, e ou trava no WaitForChild ou passa direto sem tocar nada. Não há mensagem de erro dizendo "este rig não é um personagem" — a animação simplesmente não acontece.
Próximo passo
Quando o movimento próprio estiver funcionando, o passo seguinte é decidir se ele substitui algo em vez de somar. O personagem padrão da Roblox já vem com animações de correr, escalar, nadar e pular, e a documentação descreve os dois caminhos lado a lado: tocar animação manualmente por script, ou substituir as animações padrão do personagem.
A troca é mais simples do que parece e não exige animar nada: dá para pegar um id do catálogo. A própria documentação dá o exemplo de trocar a corrida padrão pela variante Ninja Run, com o id 656118852. O script que faz essa troca vai em ServerScriptService, e ele começa parando as faixas que já estão tocando antes de reescrever as referências do Animate.
É um bom primeiro exercício justamente por não ter nada de autoral: se a corrida do seu jogo mudar, o encanamento está de pé, e aí vale investir as horas do editor no movimento que só o seu jogo tem.
Fontes
- Animation Editor | Documentation - Roblox Creator Hub — consultada em
- Use animations | Documentation - Roblox Creator Hub — consultada em
Artefato pronto pra usar
-- ServerScriptService: um módulo pequeno que resolve os DOIS casos da
-- documentação — rig com Humanoid (personagem) e rig sem Humanoid
-- (porta, bicho, alavanca) — e guarda a faixa já carregada em vez de
-- carregar de novo a cada uso.
--
-- Trocar o id abaixo pelo da SUA animação publicada.
local Animacoes = {}
local ID_DO_CHUTE = "rbxassetid://2515090838"
-- cache: rig -> { [animationId] = AnimationTrack }
local faixas = {}
-- O Animator é quem carrega a faixa. Em personagem ele mora no Humanoid.
-- Em rig sem Humanoid a documentação manda criar AnimationController com
-- um Animator filho — sem isso, LoadAnimation não tem onde acontecer.
local function animatorDe(rig)
local humanoid = rig:FindFirstChildOfClass("Humanoid")
if humanoid then
return humanoid:WaitForChild("Animator", 5)
end
local controller = rig:FindFirstChildOfClass("AnimationController")
if not controller then
controller = Instance.new("AnimationController")
controller.Parent = rig
end
local animator = controller:FindFirstChildOfClass("Animator")
if not animator then
animator = Instance.new("Animator")
animator.Parent = controller
end
return animator
end
-- Devolve a faixa pronta para tocar. Carrega uma vez por rig.
function Animacoes.faixa(rig, animationId)
local animator = animatorDe(rig)
if not animator then
warn("sem Animator em " .. rig:GetFullName() .. ": animação não vai tocar")
return nil
end
faixas[rig] = faixas[rig] or {}
if faixas[rig][animationId] then
return faixas[rig][animationId]
end
local animation = Instance.new("Animation")
animation.AnimationId = animationId
local track = animator:LoadAnimation(animation)
faixas[rig][animationId] = track
-- rig removido do jogo leva o cache junto, senão isto vaza
rig.AncestryChanged:Connect(function(_, parent)
if not parent then
faixas[rig] = nil
end
end)
return track
end
function Animacoes.tocar(rig, animationId)
local track = Animacoes.faixa(rig, animationId)
if track then
track:Play()
end
return track
end
-- Exemplo: tocar no personagem de quem entra, e escutar o marcador.
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
character:WaitForChild("Humanoid")
local track = Animacoes.faixa(character, ID_DO_CHUTE)
if not track then
return
end
-- só dispara se a animação tiver um marcador com esse nome
track:GetMarkerReachedSignal("KickEnd"):Connect(function(parametro)
print(player.Name .. " terminou o chute", parametro)
end)
end)
end)
return Animacoes


