Leaderboard no Roblox: a pasta que precisa se chamar leaderstats, em minúsculo
O placar embutido do Roblox tem três abas e duas fontes de dado diferentes. A aba Here sai de uma pasta chamada leaderstats — e o nome dela, em minúsculo, é a diferença entre funcionar e não aparecer nada.
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

Existe um bug de Roblox que tem uma assinatura inconfundível: o script roda sem erro, o output está limpo, e o placar simplesmente não mostra nada. Nenhuma mensagem, nenhuma pista.
A causa é quase sempre uma letra maiúscula. Este guia explica o placar embutido do começo ao fim — as três abas, as duas fontes de dado, e por que o nome de uma pasta é a coisa mais importante do assunto.
O problema
O Roblox tem um placar embutido, dentro da PlayerList. Ou seja: antes de desenhar interface, existe um lugar pronto onde a estatística do jogador aparece, e ele já está na tela.
O que confunde é que esse lugar tem três abas, e elas não vêm do mesmo lugar. A Here mostra a classificação da sessão, dos jogadores no servidor atual. Friends e Global mostram classificação persistente, que vem de um ordered data store registrado no Creator Hub — a Global compara todos os jogadores da experiência.
A divisão de trabalho é limpa e vale memorizar: o leaderstats alimenta a aba Here; o ordered data store alimenta Friends e Global. São sistemas independentes. Montar o leaderstats não popula a Global, e registrar um ordered data store não muda a Here.
A maior parte dos jogos precisa só da primeira, e é dela que trata o resto deste texto.
Vale dizer por que usar o embutido em vez de desenhar o seu. Não é preguiça: o placar da PlayerList já está no lugar onde o jogador procura, já funciona no celular e no console, já lida com entrada e saída de gente, e não gasta um pixel da sua interface. Um placar próprio precisa resolver tudo isso de novo, e a maior parte dos que se vê por aí resolve pior.
O caso legítimo para o placar próprio é quando a informação não cabe na forma de colunas — barra de progresso, ícone, cor, agrupamento por time. Se o que você quer mostrar é número ao lado de nome, o embutido é a resposta certa, e a discussão acaba aí.
Há ainda um efeito de segunda ordem que costuma decidir a questão: o que está no leaderstats é lido por outras partes do ecossistema. É a estrutura que o Roblox conhece, e código de terceiros, plugin e ferramenta de moderação esperam encontrá-la. Guardar o progresso só numa tabela sua funciona e isola o seu jogo de tudo isso.
Passo a passo
1. Crie o script. O passo oficial é um Script em ServerScriptService chamado Leaderboard. Servidor, não cliente: o placar é estado de jogo, e estado de jogo mora no servidor.
2. Conecte ao PlayerAdded. Tudo acontece quando alguém entra.
3. Crie a pasta. Dentro da função conectada, crie um Folder, chame de leaderstats e defina o jogador como pai.
A documentação para a explicação aqui para dizer uma coisa em voz alta, e vale repetir literalmente: é essencial que a pasta se chame leaderstats, todo em minúsculo. O Roblox não adiciona o jogador ao placar se o nome for qualquer outro.
4. Acrescente as estatísticas. Placar usa objetos de valor para guardar e mostrar os números: IntValue para inteiro, e há também NumberValue e StringValue.
Três detalhes que vêm juntos e definem o comportamento. O nome do objeto é exatamente como a estatística aparece no placar — não existe rótulo separado, o nome é o rótulo. O valor de IntValue, NumberValue e StringValue precisa ser definido pela propriedade Value, e não atribuído ao objeto. E é o objeto ter a pasta leaderstats como pai que o coloca no placar: enquanto o Parent não for definido, o objeto existe e não aparece.
5. Atualize durante a partida. Atualizar é mudar a propriedade Value daquela estatística dentro da pasta do jogador. O exemplo oficial é um objeto coletável que, ao ser tocado, se destrói e soma na estatística de quem pegou.
6. Controle a ordem. Existem três formas, e elas se combinam de um jeito específico.
A primeira é a mais simples: acrescentar as estatísticas na ordem em que devem aparecer. A segunda é um BoolValue filho chamado IsPrimary, com valor verdadeiro, que põe aquela estatística em primeiro. A terceira é um NumberValue filho chamado Priority, com valor inteiro — prioridade mais alta aparece mais cedo, e estatística sem prioridade vale zero por padrão.
A regra de combinação está escrita e evita uma tarde de tentativa e erro: o IsPrimary tem precedência sobre qualquer Priority. E se várias estatísticas tiverem IsPrimary verdadeiro, aí sim o Priority delas decide a ordem entre elas.
Artefato
O script abaixo faz o que o exemplo oficial faz, com uma diferença de organização que paga no terceiro mês: as estatísticas são declaradas numa tabela, não criadas uma a uma no meio da função.
O ganho é concreto. A ordem do placar passa a ser legível numa tela só, em vez de estar implícita na ordem das linhas espalhadas. Acrescentar uma estatística vira acrescentar uma linha. E o IsPrimary e o Priority viram campos da declaração, em vez de mais quatro linhas de Instance.new cada.
Ele também traz um gancho vazio de persistência, deixado separado de propósito: o placar não deve saber o que é um DataStore. Quando a hora chegar, basta preencher uma função.
E um ajudante — Placar.somar — que existe por um motivo específico: sem ele, cada ponto do jogo que mexe no placar navega a árvore por conta própria, e um nome digitado errado falha em silêncio. Com ele, falha com aviso.
Erro comum
O erro campeão é o nome da pasta, e ele merece um parágrafo só porque a forma como ele falha é a pior possível.
Leaderstats, LeaderStats, leaderStats — todos parecem certos ao olho, todos criam uma pasta perfeitamente válida dentro do jogador, e nenhum funciona. Não há erro no output, não há exceção, não há nada a depurar: o placar fica vazio porque o Roblox não reconheceu a pasta. Quem não sabe da regra fica horas conferindo o valor da estatística, que está certo o tempo todo.
A segunda armadilha é da mesma família: atribuir o valor ao objeto em vez de à propriedade. gold = 10 no lugar de gold.Value = 10. A primeira forma joga fora a referência ao objeto e a variável passa a valer um número. O placar continua mostrando o valor inicial, e nada reclama.
A terceira é de ordem de operações. Definir o Parent do objeto antes de terminar de configurá-lo faz a estatística aparecer no placar meio pronta — o nome ainda padrão, o valor ainda zerado — e depois mudar sozinha na cara do jogador. Configurar tudo e definir o Parent por último resolve, e é o que o artefato faz.
A quarta é de escopo: montar o placar num LocalScript. Funciona na tela de quem testou, não existe para mais ninguém, e some quando o personagem renasce.
E há uma quinta, mais sutil, que só aparece em jogo com alguma idade: montar o leaderstats dentro do CharacterAdded em vez do PlayerAdded. A diferença não aparece no primeiro teste, porque o personagem nasce logo depois do jogador entrar e tudo parece certo. Ela aparece quando o jogador morre: o personagem novo dispara o evento de novo, o script cria uma segunda pasta leaderstats, e a partir daí existem duas — a antiga, que o placar está mostrando, e a nova, que o resto do código está atualizando. O número congela na tela enquanto o valor real continua subindo.
O diagnóstico é rápido quando se sabe o que procurar: abra o Explorer durante um teste, encontre o jogador e conte quantas pastas existem debaixo dele. Se houver mais de uma, o bug é esse. A regra que evita: leaderstats é do jogador, não do personagem, e se monta uma vez por sessão.
Próximo passo
Com a aba Here funcionando, o passo seguinte natural é decidir se você quer as outras duas. Elas exigem coisa diferente: um ordered data store registrado no Creator Hub, que é o que sustenta classificação persistente entre jogadores e entre amigos.
Vale medir a vontade antes de construir. Placar global é poderoso e caro de manter honesto — ele vira alvo de exploit, precisa lidar com valores absurdos e com quem descobriu um atalho, e um placar global visivelmente fraudado faz mais mal à percepção do jogo do que placar nenhum.
Antes disso, existe um trabalho mais barato e de retorno maior: decidir quais estatísticas merecem estar lá. O placar aparece em toda a tela, o tempo todo, e cada coluna nova rouba espaço e atenção das outras. Duas ou três bem escolhidas comunicam progresso; seis comunicam que ninguém decidiu o que importa.
Fontes
- Leaderboards | Documentation - Roblox Creator Hub — consultada em
Artefato pronto pra usar
-- ServerScriptService, Script chamado "Leaderboard".
--
-- A pasta TEM que se chamar "leaderstats", todo em minúsculo. Qualquer
-- outro nome e o jogador simplesmente não entra no placar — sem erro,
-- sem aviso, sem nada no output.
local Players = game:GetService("Players")
-- Declarar as estatísticas numa tabela, em vez de criar uma a uma no meio
-- da função, resolve a ordem e deixa a lista inteira visível numa tela.
--
-- nome -> é EXATAMENTE o texto que aparece na coluna
-- classe -> IntValue para inteiro, NumberValue para decimal,
-- StringValue para texto
-- inicial -> valor no começo da sessão
-- principal -> IsPrimary: manda para a primeira posição
-- prioridade-> Priority: maior aparece antes. Sem isto, vale 0.
local ESTATISTICAS = {
{ nome = "Moedas", classe = "IntValue", inicial = 0, principal = true },
{ nome = "Nivel", classe = "IntValue", inicial = 1, prioridade = 10 },
{ nome = "Tempo", classe = "StringValue", inicial = "00:00", prioridade = 5 },
}
-- Gancho de persistência. Devolva uma tabela { [nome] = valor } para
-- começar a sessão com o que estava salvo, ou nil para usar os iniciais.
-- Deixado separado de propósito: o placar não deve saber de DataStore.
local function carregarSalvo(_player)
return nil
end
local function montar(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats" -- minúsculo. Não mexa.
local salvo = carregarSalvo(player)
for _, def in ESTATISTICAS do
local stat = Instance.new(def.classe)
stat.Name = def.nome
stat.Value = (salvo and salvo[def.nome] ~= nil) and salvo[def.nome] or def.inicial
if def.principal then
local isPrimary = Instance.new("BoolValue")
isPrimary.Name = "IsPrimary"
isPrimary.Value = true
isPrimary.Parent = stat
end
if def.prioridade then
local priority = Instance.new("NumberValue")
priority.Name = "Priority"
priority.Value = def.prioridade
priority.Parent = stat
end
-- o parent é o que coloca a estatística no placar; por último,
-- para o objeto já ir completo
stat.Parent = leaderstats
end
leaderstats.Parent = player
end
-- Ajudante para o resto do jogo: soma sem precisar navegar a árvore
-- em todo lugar, e avisa quando a estatística não existe em vez de
-- falhar calado.
local Placar = {}
function Placar.somar(player, nome, quanto)
local leaderstats = player:FindFirstChild("leaderstats")
local stat = leaderstats and leaderstats:FindFirstChild(nome)
if not stat then
warn("estatistica inexistente no placar: " .. tostring(nome))
return
end
stat.Value += quanto
end
Players.PlayerAdded:Connect(montar)
return Placar


