Moon Animator travou? Os 5 pontos de falha, em ordem
O Moon Animator não abre, não move o rig ou exporta uma animação que não toca no jogo. Cada um desses sintomas tem uma causa diferente — este texto separa os cinco e te dá um auditor de rig para rodar antes de animar.
Rascunho assistido por IA, revisado, testado e editado por um humano antes de publicar. Ver Política Editorial. · Revisado por Gustavo Cantino, 20/09/2026 Política Editorial

"Moon animator not working" não é um problema: são cinco, e eles não se consertam do mesmo jeito. Ou o botão do plugin não aparece na aba Plugins, ou a janela abre e a timeline fica vazia, ou você mexe o rig e nada se move, ou o Export dá erro, ou a animação sobe bonitinha e no jogo o personagem continua em T-pose. Antes de reinstalar o plugin pela terceira vez — o que resolve exatamente um desses cinco casos — descubra qual dos cinco é o seu. Leva três minutos e economiza a tarde.
Cinco sintomas diferentes chamados de "não funciona"
A) O botão não aparece. Você instalou pelo site, voltou pro Studio e a aba Plugins não mudou. Isso é instalação ou ativação, nunca rig. Custa uns 20 minutos de gente procurando em menu errado.
B) A janela abre, a timeline fica vazia. Você clica em adicionar o rig e ele não entra na lista, ou entra e some. Aqui o suspeito é o rig (sem Humanoid, sem Motor6D) ou um conflito de duas versões do plugin instaladas ao mesmo tempo.
C) O rig não se move. Você arrasta o braço, a curva aparece na timeline, e a parte fica parada. Isso é junta: Motor6D ausente, Part0/Part1 vazios, ou uma parte com Anchored = true no meio do galho.
D) O Export falha. O plugin pede o nome, você confirma e vem erro, ou nada acontece e o Output cospe uma linha vermelha. Aqui é permissão de conta/grupo ou rig inválido para virar KeyframeSequence.
E) Sobe e não toca. Esse é o mais caro dos cinco, porque só aparece no fim do ciclo. Você animou 40 movimentos, exportou tudo, colou os IDs, deu Play e nada. Cada ciclo animar → exportar → testar leva de 5 a 15 minutos; descobrir no item 40 que os 40 estão na conta errada é uma hora de re-upload mais a troca de todos os IDs espalhados nos scripts.
A ordem de diagnóstico abaixo segue a frequência real: começa no mais barato de checar e termina no mais caro de consertar.
Diagnóstico em ordem: plugin, permissão, rig, save, export
1. Plugin instalado não é plugin ativado (30 segundos). Vá em Plugins → Manage Plugins. Se o Moon Animator está na lista mas desmarcado, marque e reabra o Studio. Se não está na lista, você comprou/instalou logado em uma conta e abriu o Studio em outra — acontece muito com quem tem conta de teste. E se você instalou com o Studio aberto, feche todas as janelas do Studio e abra de novo: plugin novo só carrega na inicialização.
2. Duas versões brigando (2 minutos). Plugins soltos como arquivo .rbxm na pasta local de plugins do Studio carregam junto com os da loja. Se você já baixou o Moon Animator manualmente algum dia e depois instalou pela loja, existem dois botões e um deles está quebrado — normalmente o antigo, que perdeu API. Abra a pasta local de plugins pelo botão Plugins Folder do Studio, apague duplicatas e cópias antigas do Moon Animator 1, e reabra. Com o Output aberto (View → Output), procure a primeira linha vermelha com o nome do plugin: ela é a única que importa, o resto é consequência.
3. Permissão negada não pergunta de novo. Plugin que pede acesso a script ou a requisições externas mostra o prompt uma vez. Se você clicou Deny naquele dia, o plugin segue rodando meio funcional para sempre e você não vê aviso nenhum. Volte em Manage Plugins, abra as permissões do Moon Animator e libere o que estiver bloqueado.
4. O rig — aqui mora a maioria dos casos B e C. O Moon Animator anima Motor6D, e só. Ele não anima Weld, não anima WeldConstraint, não anima parte ancorada e não anima parte cujo Motor6D está com Part0 ou Part1 vazio (o caso clássico de rig importado do Blender via FBX e montado na mão depois).
Checklist do rig que funciona:
ModelcomPrimaryPartdefinido (normalmente a HumanoidRootPart);- um
Humanoidou umAnimationControllerdentro do Model; - todas as partes com
Anchored = false; - um
Motor6Dpor junta, comPart0sendo o pai ePart1o filho; - nome único por parte — duas partes chamadas "Handle" e o plugin escolhe uma delas no export.
Junta faltando você cria na mão:
local rig = workspace.Dummy
local joint = Instance.new("Motor6D")
joint.Name = "Neck"
joint.Part0 = rig.UpperTorso
joint.Part1 = rig.Head
joint.C0 = rig.UpperTorso.CFrame:Inverse() * rig.Head.CFrame
joint.Parent = rig.UpperTorsoEm vez de conferir isso item por item em cada rig, rode o auditor da próxima seção. Ele devolve a lista de problemas em um print.
5. Teste do arquivo limpo (90 segundos). Este é o passo que separa "o plugin quebrou" de "o meu arquivo quebrou", e é o que quase ninguém faz. Abra um Baseplate novo, gere um dummy pelo Rig Builder, abra o Moon Animator, crie dois keyframes e salve. Funcionou? Então o plugin está inteiro e o problema é o seu lugar: save corrompido, rig bagunçado ou outro plugin conflitando. Não funcionou nem no arquivo limpo? Aí sim é instalação/versão, e você volta pros passos 1 a 3 com a consciência tranquila.
6. Export. Rig sem Humanoid/AnimationController e rig com junta inválida derrubam o export. Resolvidos esses, o que sobra é permissão de publicação: se o jogo é de grupo, a animação precisa ser criada como o grupo. Confira a opção de dono na janela de export antes de clicar em salvar — é um clique que decide se você vai refazer tudo depois.
O auditor de rig que você roda antes de abrir a timeline
O artefato desta página é um Script com --!strict que varre o seu rig e imprime os problemas que travam o Moon Animator: PrimaryPart vazio, falta de Humanoid/AnimationController, partes ancoradas, nomes duplicados, Motor6D com Part0/Part1 nulos, junta apontando pra fora do rig e juntas faltando no padrão R6 ou R15 (ele detecta qual dos dois seu rig está mais perto de ser).
Como usar: cole em um Script dentro de ServerScriptService, troque RIG_NAME pelo nome do Model do rig no Workspace e aperte Run (F8) — Run, não Play, porque você quer o estado de edição do rig, não o personagem que o jogo cria. Leia o Output: linhas de warn são o que precisa consertar, a linha que começa com OK é o resumo. Roda em menos de um segundo em rig de 15 juntas e substitui a inspeção manual no Explorer.
O segundo artefato é o rig-check.json: o mesmo checklist em formato de dado, para ficar ao lado do .blend e do seu script de exportação. Serve pra travar o padrão do projeto quando mais de uma pessoa monta rig — inclusive o dono do asset no export, que é a causa do erro da próxima seção.
O erro caro: a animação exportada na conta errada
Animação no Roblox só carrega se o dono do asset for o mesmo dono da experiência. Jogo de grupo exige animação criada pelo grupo. Se você exportou pela sua conta pessoal, o ID existe, abre no site, toca no editor — e no jogo publicado não acontece nada. O sintoma é traiçoeiro justamente por isso: você jura que o Moon Animator não funciona, quando o problema é de propriedade do asset.
E tem um agravante que dobra a confusão:
local anim = Instance.new("Animation")
anim.AnimationId = "rbxassetid://0000000000"
humanoid:LoadAnimation(anim):Play() -- depreciado e engole o erroA forma certa passa pelo Animator e checa o resultado:
local animator = humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", humanoid)
local ok, track = pcall(function() return animator:LoadAnimation(anim) end)
if not ok then warn("animacao nao carregou:", anim.AnimationId, track) return end
track.Priority = Enum.AnimationPriority.Action
track:Play()Sem o warn, falha de carregamento vira silêncio e você passa uma hora procurando bug de script. Com ele, o Output te entrega o ID exato do asset que está na conta errada.
O conserto: re-exporte a animação escolhendo o grupo como dono e troque o ID. Se forem 40 animações, cada re-upload leva algo entre 30 e 60 segundos, mais a troca do ID no código — é a diferença entre um minuto de atenção no export e uma hora de trabalho repetido. Se seus IDs estão hardcoded espalhados em vários scripts, esse prejuízo dobra.
O que medir depois
Duas métricas dizem se o seu pipeline de animação está saudável. A primeira é o tempo do ciclo: quantos minutos entre "terminei o movimento na timeline" e "vi ele rodando no jogo publicado". Cronometre uma vez. Se passa de 15 minutos, o gargalo quase sempre é export manual e ID colado na mão.
A segunda é quantos warns o auditor devolve no primeiro Run de cada rig novo. Rig que nasce com zero warn não gera nenhum dos casos B, C e D deste texto. Se todo rig seu nasce com três ou quatro warns, o problema não é o Moon Animator: é o seu processo de montar rig. Salve um rig aprovado como template em ReplicatedStorage e clone a partir dele em vez de montar de novo.
Feito isso, tire os IDs de animação de dentro dos scripts e coloque todos num ModuleScript único, com fallback e warn no carregamento. Assim, o dia em que você precisar re-exportar tudo para um grupo, a troca acontece em um arquivo só.
Artefato pronto pra usar
--!strict
-- Auditor de rig para Moon Animator.
-- Onde mora: Script dentro de ServerScriptService.
-- Como rodar: ajuste RIG_NAME, aperte Run (F8) e leia o Output.
-- Warn = conserte antes de abrir a timeline. OK = resumo.
local RIG_NAME: string = "Dummy"
local R15: { string } = {
"Root", "Waist", "Neck",
"LeftShoulder", "LeftElbow", "LeftWrist",
"RightShoulder", "RightElbow", "RightWrist",
"LeftHip", "LeftKnee", "LeftAnkle",
"RightHip", "RightKnee", "RightAnkle",
}
local R6: { string } = {
"RootJoint", "Neck",
"Left Shoulder", "Right Shoulder",
"Left Hip", "Right Hip",
}
type Report = { string }
local function contains(list: { string }, value: string): boolean
for _, v in list do
if v == value then
return true
end
end
return false
end
local function audit(rigName: string): Report
local report: Report = {}
local rig = workspace:FindFirstChild(rigName)
if not rig or not rig:IsA("Model") then
table.insert(report, "FATAL: nao existe Model chamado " .. rigName .. " no Workspace.")
return report
end
-- 1. PrimaryPart: sem ele o plugin erra a referencia de raiz
if not rig.PrimaryPart then
table.insert(report, "PrimaryPart vazio: defina a HumanoidRootPart como PrimaryPart do Model.")
end
-- 2. Controlador: sem Humanoid nem AnimationController o rig nao aparece na lista
local hasController = rig:FindFirstChildOfClass("Humanoid") ~= nil
or rig:FindFirstChildOfClass("AnimationController") ~= nil
if not hasController then
table.insert(report, "Sem Humanoid e sem AnimationController: adicione um dos dois dentro do Model.")
end
local joints: { Motor6D } = {}
local partNames: { [string]: number } = {}
for _, d in rig:GetDescendants() do
if d:IsA("Motor6D") then
table.insert(joints, d)
local p0, p1 = d.Part0, d.Part1
if p0 == nil or p1 == nil then
table.insert(report, "Motor6D " .. d:GetFullName() .. " com Part0 ou Part1 vazio.")
elseif not p0:IsDescendantOf(rig) or not p1:IsDescendantOf(rig) then
table.insert(report, "Motor6D " .. d.Name .. " aponta para parte fora do rig.")
end
elseif d:IsA("BasePart") then
if d.Anchored then
table.insert(report, "Parte ancorada: " .. d.Name .. " (Anchored = true trava tudo abaixo dela).")
end
partNames[d.Name] = (partNames[d.Name] or 0) + 1
elseif d:IsA("Weld") or d:IsA("WeldConstraint") then
table.insert(report, "Junta rigida " .. d.ClassName .. " em " .. d:GetFullName() .. ": troque por Motor6D se essa parte precisa animar.")
end
end
-- 3. Nomes duplicados quebram o export do KeyframeSequence
for name, count in partNames do
if count > 1 then
table.insert(report, "Nome duplicado: " .. tostring(count) .. " partes chamadas " .. name .. ".")
end
end
if #joints == 0 then
table.insert(report, "FATAL: zero Motor6D no rig. O Moon Animator so move Motor6D.")
return report
end
-- 4. Descobre se o rig esta mais perto de R6 ou R15 e cobra as juntas faltando
local jointNames: { string } = {}
for _, j in joints do
table.insert(jointNames, j.Name)
end
local r15Hits, r6Hits = 0, 0
for _, n in jointNames do
if contains(R15, n) then
r15Hits += 1
end
if contains(R6, n) then
r6Hits += 1
end
end
local isR15 = r15Hits >= r6Hits
local expected: { string } = if isR15 then R15 else R6
local label: string = if isR15 then "R15" else "R6"
for _, n in expected do
if not contains(jointNames, n) then
table.insert(report, "Junta " .. label .. " faltando: " .. n .. ".")
end
end
table.insert(report, "OK: " .. tostring(#joints) .. " Motor6D encontrados, padrao mais proximo: " .. label .. ".")
return report
end
local result = audit(RIG_NAME)
print("=== AUDITOR DE RIG: " .. RIG_NAME .. " ===")
for _, line in result do
if string.sub(line, 1, 2) == "OK" then
print(line)
else
warn(line)
end
end
print("=== " .. tostring(#result) .. " linha(s) no relatorio ==="){
"rigName": "Dummy",
"rigType": "R15",
"primaryPart": "HumanoidRootPart",
"controller": "Humanoid",
"requiredMotor6D": [
"Root", "Waist", "Neck",
"LeftShoulder", "LeftElbow", "LeftWrist",
"RightShoulder", "RightElbow", "RightWrist",
"LeftHip", "LeftKnee", "LeftAnkle",
"RightHip", "RightKnee", "RightAnkle"
],
"reject": {
"anchoredParts": true,
"duplicatePartNames": true,
"weldOnAnimatedParts": true,
"nullJointParts": true
},
"export": {
"assetOwner": "group",
"groupId": 0,
"defaultPriority": "Action",
"namePrefix": "anim_",
"notes": "groupId 0 = preencher com o grupo dono da experiencia. Animacao de conta pessoal nao carrega em jogo de grupo."
}
}

