UGC e itens

Item UGC rejeitado na moderação: como achar a causa real

Seu acessório voltou como rejeitado e a mensagem da moderação não diz o que estava errado. Este texto separa as cinco causas possíveis em ordem de custo e entrega um validador que roda no Studio antes de você queimar a próxima taxa de upload.

por Gustavo Cantino13 min de leituraIntermediário

Rascunho assistido por IA, revisado, testado e editado por um humano antes de publicar. Ver Política Editorial. · Revisado por Gustavo Cantino, 05/09/2026 Política Editorial

Placa tipográfica com a categoria UGC e itens em destaque, o nível intermediário abaixo, e um campo de barras verticais verdes sobre fundo escuro.

Seu item UGC foi rejeitado, chegou uma notificação genérica falando em violação das Regras da Comunidade e você continua sem saber o que exatamente estava errado no acessório. Isso não é falha do sistema: o mesmo texto padrão cobre cinco causas diferentes — nome, descrição, textura, malha e categoria — e a moderação não detalha qual delas pegou. Dá pra eliminar as cinco em ordem, da mais barata pra mais cara, e chegar na culpada em uns 15 minutos, sem reenviar às cegas e sem torrar taxa de upload no chute.

Sua mensagem de rejeição não diz o motivo, e isso custa Robux

O prejuízo aqui é medido em Robux, não em tempo. A taxa de publicação do acessório é cobrada no momento em que você confirma o upload no Creator Dashboard, não quando o item é aprovado — item recusado é taxa queimada. Com o pacote de 800 Robux custando na casa dos R$ 40 no varejo brasileiro, cada tentativa perdida sai por perto disso. Quem sobe uma leva de cinco itens e leva três rejeições jogou fora o preço de um jogo indie por causa de uma palavra na descrição.

Tem um custo que não aparece em lugar nenhum: histórico. Rejeição de moderação não é só "não passou", é um registro na sua conta. Acumular rejeições seguidas do mesmo tipo — principalmente as que a Roblox classifica como tentativa de burlar filtro — é o caminho mais rápido pra perder o acesso à publicação de itens de avatar. Ninguém avisa que você está perto do limite; você descobre quando o botão some.

Antes de investigar, separe dois eventos que quase todo mundo mistura:

Erro de validação no upload. É a mensagem técnica que aparece na hora, ainda na tela de publicação: malha com triângulos demais, textura acima do tamanho permitido, attachment ausente, mais de um MeshPart dentro do Handle. Aqui nada foi moderado — o item nem entrou na fila. É problema de arquivo, resolve no Blender.

Rejeição de moderação. O item foi aceito tecnicamente, entrou na fila e voltou marcado como rejeitado na aba Creations, de minutos a alguns dias depois. Aqui um humano ou um classificador olhou o conjunto: imagem renderizada, nome, descrição e a malha. É deste caso que este texto trata.

Se o que você recebeu foi a primeira coisa, pare de reescrever a descrição — não é isso. Se foi a segunda, siga a triagem abaixo na ordem.

Triagem em 6 passos, do mais barato pro mais caro

1. Nome e descrição. É a causa mais comum e a mais boba. Nome de personagem de outra empresa (Naruto, Sonic, Goku, Mickey), marca real (Nike, Gucci, Supreme), nome de rede social, link, arroba, menção a "free", "grátis", "Robux", "promo code", qualquer coisa que soe a promessa comercial fora da plataforma. Escrever com números no lugar de letras — N4ruto, G0ku — é pior do que escrever certo: vira tentativa deliberada de burlar filtro, que é uma infração mais grave que a original. Reescreva o nome como descrição física do objeto: "Bandana Laranja com Placa de Metal" passa onde "Naruto Headband" não passa.

2. Textura. Texto legível dentro da textura é o segundo motivo mais frequente. Qualquer palavra escrita na imagem — inclusive sua assinatura, seu @ ou o nome do seu grupo — é lida como texto não moderado e derruba o item. Some a isso: logos reconhecíveis, símbolos políticos ou religiosos controversos, sangue, e o clássico desenho escondido num canto do UV que ninguém vai ver no jogo. A moderação olha o arquivo de textura, não o render bonito. Se você comprou ou baixou a textura, revise pixel a pixel o que veio junto.

3. Malha. Formas que reproduzem anatomia humana de forma realista, armas de fogo realistas, itens que na prática viram um avatar inteiro em vez de um acessório, e malha invisível ou com transparência alta usada pra esconder o volume real. Transparência acima de zero num Handle de acessório é sinal vermelho automático pra qualquer revisor: a leitura padrão é que você está escondendo alguma coisa.

4. Categoria e attachment. Publicar um chapéu na categoria de acessório de rosto, ou subir uma peça de layered clothing sem cage, aparece pra quem revisa como item mal classificado — e mal classificado é motivo de recusa. O nome do Attachment dentro do Handle é o que define onde o item encaixa, e ele precisa ser exatamente um dos nomes que a Roblox reconhece. Isto aqui é o erro que mais vejo em item de quem está começando:

Command bar do Studio
-- errado: nome livre no attachment
local a = Instance.new("Attachment")
a.Name = "Chapeu" -- a Roblox não reconhece, o item encaixa torto ou é recusado
a.Parent = workspace.Accessory.Handle

Os nomes válidos são fixos: HatAttachment, HairAttachment, FaceFrontAttachment, NeckAttachment, FrontAttachment, BackAttachment, WaistFrontAttachment, WaistBackAttachment, WaistCenterAttachment, LeftShoulderAttachment e RightShoulderAttachment. Um Handle, um Attachment, nome exato, sem sobrar.

5. Semelhança com item que já existe. Se a sua malha é muito parecida com a de outro criador — porque você partiu do mesmo template, do mesmo pack do Sketchfab ou porque literalmente copiou — o item pode voltar por denúncia de propriedade intelectual, mesmo dias depois de aprovado. Item que já está à venda e some do catálogo do nada costuma ser isso.

6. Histórico da conta. Se os passos de 1 a 5 estão limpos e ainda assim tudo que você sobe volta, o problema pode não estar no item. Conta com strikes recentes entra numa fila mais rígida. Nesse caso a saída é parar de subir por alguns dias, resolver as moderações abertas no suporte e voltar com um item obviamente inofensivo pra testar o canal.

Rodar essa triagem na mão em cada item é o que consome os 15 minutos. O que dá pra automatizar é a parte chata — estrutura, tamanho, transparência e palavras de risco no texto — e é isso que o script abaixo faz.

O validador que roda antes de você gastar Robux

O artefato é um Script comum que você cola em ServerScriptService. Ele lê tudo que estiver dentro de uma pasta chamada UGC_Check em ServerStorage, e para cada Accessory faz sete verificações: existe Handle, existe exatamente um Attachment com nome reconhecido, o tamanho cabe na caixa daquele ponto de encaixe, a malha não está transparente, não tem Script nem Decal escondido dentro, existe textura ou SurfaceAppearance, e o nome mais a descrição não batem com a lista de termos de risco.

A descrição não mora no modelo — ela mora no site. Por isso o script lê um atributo chamado Descricao no próprio Accessory. Antes de rodar, selecione o item, vá em Properties, adicione o atributo Descricao como string e cole ali o texto exato que você vai colar no Creator Dashboard. É esse texto que precisa passar, não uma versão aproximada.

Pra usar: cole o script, crie a pasta, arraste os acessórios pra dentro, aperte Play e leia o Output. Linha com REPROVA é bloqueio — não suba. Linha com ATENCAO é decisão sua. Zero linhas significa que a estrutura está limpa e sobrou o que o script não consegue ver: contagem de triângulos e o conteúdo visual da textura, que continuam sendo trabalho de olho humano no Blender.

Os limites de caixa e a lista de termos ficam no topo do arquivo, editáveis. Confirme os valores atuais na documentação de especificação de acessórios antes de rodar em cima de uma leva grande: a Roblox mexe nesses números sem avisar, e um validador desatualizado é pior que nenhum, porque te dá confiança falsa.

O erro caro: reenviar o mesmo item até passar

O reflexo depois da rejeição é subir de novo. Trocar uma letra no nome, apertar publicar, torcer. É o pior movimento possível por dois motivos.

Primeiro, cada reenvio paga a taxa outra vez. Três tentativas no escuro custam três vezes o preço de publicação e não te dão nenhuma informação nova, porque a mensagem de retorno continua sendo a mesma frase genérica. Você está pagando pra receber o mesmo texto.

Segundo, e mais grave: reenvio repetido do mesmo conteúdo recusado é lido como tentativa de forçar passagem. Isso escala a punição de "item rejeitado" pra "conta moderada", e conta moderada tira seu acesso à publicação de itens de avatar por um período — ou de vez, se já houver histórico.

O caminho certo depois de uma rejeição é: primeiro rodar a triagem e o validador, segundo mudar de verdade a coisa que você identificou (nome inteiro, textura regravada, malha remodelada — não uma letra), e terceiro, se você tem certeza de que o item está limpo, abrir um pedido de revisão no suporte em vez de reenviar. Um item por vez, e só depois que o anterior teve resposta. Se você não consegue apontar qual das cinco causas era, você não corrigiu nada — só mexeu.

O que medir na próxima leva

Abra uma planilha com cinco colunas: nome do item, data e hora do publish, data e hora da resposta, resultado, e a causa que você identificou depois. Trinta itens nessa planilha valem mais que qualquer palpite de fórum.

Duas métricas saem dela. A primeira é sua taxa de aprovação por leva — se ela está abaixo de 80%, o problema é sistêmico no seu pipeline, provavelmente textura ou nomenclatura, e não azar de moderação. A segunda é o tempo médio de resposta: se você tem um baseline de quanto costuma demorar, consegue saber quando um item está travado de verdade e vale abrir suporte, em vez de esperar mais uma semana sem motivo.

Com trinta linhas você também descobre qual das cinco causas é a sua causa. Quase todo criador tem uma dominante, e ela quase nunca é a que ele imaginava. Quando você souber qual é a sua, adicione a verificação correspondente na lista de termos do validador e ela nunca mais volta.

Artefato pronto pra usar

Script em ServerScriptService
lua
--!strict
--[[
	Validador de item UGC antes do upload.

	COMO USAR
	1. Cole este Script em ServerScriptService.
	2. Crie uma pasta chamada "UGC_Check" dentro de ServerStorage.
	3. Arraste pra dentro dela os Accessory que voce vai publicar.
	4. Em cada Accessory, adicione um atributo string chamado "Descricao"
	   com o texto EXATO que voce vai colar no Creator Dashboard.
	5. Aperte Play (F5) e leia o Output.

	REPROVA  = nao suba assim.
	ATENCAO  = decisao sua, mas revise.

	Os limites abaixo mudam de tempos em tempos. Confirme na doc oficial
	de especificacao de acessorios antes de rodar numa leva grande.
]]

local ServerStorage = game:GetService("ServerStorage")

type Caixa = { x: number, y: number, z: number }

-- Caixa maxima (em studs) por ponto de encaixe.
local BBOX: { [string]: Caixa } = {
	HatAttachment = { x = 2.5, y = 2.5, z = 2.5 },
	HairAttachment = { x = 2.5, y = 2.5, z = 2.5 },
	FaceFrontAttachment = { x = 1.5, y = 1.5, z = 1.0 },
	NeckAttachment = { x = 2.0, y = 1.5, z = 1.5 },
	FrontAttachment = { x = 2.0, y = 2.0, z = 1.0 },
	BackAttachment = { x = 2.5, y = 3.0, z = 1.5 },
	WaistFrontAttachment = { x = 2.0, y = 1.0, z = 1.0 },
	WaistBackAttachment = { x = 2.0, y = 1.0, z = 1.0 },
	WaistCenterAttachment = { x = 2.0, y = 1.0, z = 1.0 },
	LeftShoulderAttachment = { x = 1.0, y = 2.0, z = 1.0 },
	RightShoulderAttachment = { x = 1.0, y = 2.0, z = 1.0 },
}

-- Termos que costumam derrubar nome/descricao. Adicione os seus.
local TERMOS_RISCO: { string } = {
	"naruto", "goku", "sonic", "mario", "pikachu", "mickey", "batman",
	"nike", "adidas", "gucci", "supreme", "louis vuitton",
	"discord", "tiktok", "instagram", "youtube", "twitter",
	"free", "gratis", "robux", "promo", "code", "giveaway",
	"http", "www", "@", ".com", "dm me", "add me",
	"gun", "blood", "sangue", "weed", "vape", "sexy", "nude",
}

local reprovas = 0
local atencoes = 0

local function reprova(alvo: Instance, msg: string)
	reprovas += 1
	warn(("[REPROVA] %s -> %s"):format(alvo.Name, msg))
end

local function atencao(alvo: Instance, msg: string)
	atencoes += 1
	print(("[ATENCAO] %s -> %s"):format(alvo.Name, msg))
end

-- deixa o texto comparavel: minusculo, sem separadores, sem numero-letra
local function normalizar(txt: string): string
	local baixo = string.lower(txt)
	baixo = (string.gsub(baixo, "[%-_%.%s]+", " "))
	baixo = (string.gsub(baixo, "0", "o"))
	baixo = (string.gsub(baixo, "1", "i"))
	baixo = (string.gsub(baixo, "3", "e"))
	baixo = (string.gsub(baixo, "4", "a"))
	baixo = (string.gsub(baixo, "5", "s"))
	return baixo
end

local function checarTexto(acc: Instance, rotulo: string, txt: string)
	if txt == "" then
		return
	end
	local alvo = normalizar(txt)
	for _, termo in TERMOS_RISCO do
		if string.find(alvo, termo, 1, true) then
			reprova(acc, ("%s contem termo de risco: '%s'"):format(rotulo, termo))
		end
	end
end

local function checarAccessory(acc: Accessory)
	-- 1. Handle
	local handle = acc:FindFirstChild("Handle")
	if not handle or not handle:IsA("BasePart") then
		reprova(acc, "nao tem uma BasePart chamada 'Handle'")
		return
	end

	-- 2. Attachment unico e com nome reconhecido
	local attachments: { Attachment } = {}
	for _, filho in handle:GetChildren() do
		if filho:IsA("Attachment") then
			table.insert(attachments, filho)
		end
	end

	if #attachments == 0 then
		reprova(acc, "Handle sem Attachment: o item nao encaixa em lugar nenhum")
	elseif #attachments > 1 then
		reprova(acc, ("Handle com %d Attachments; use exatamente 1"):format(#attachments))
	else
		local att = attachments[1]
		local limite = BBOX[att.Name]
		if not limite then
			reprova(acc, ("nome de Attachment invalido: '%s'"):format(att.Name))
		else
			-- 3. Caixa
			local s = handle.Size
			if s.X > limite.x or s.Y > limite.y or s.Z > limite.z then
				reprova(acc, ("tamanho %.2f x %.2f x %.2f passa do limite %.2f x %.2f x %.2f de %s")
					:format(s.X, s.Y, s.Z, limite.x, limite.y, limite.z, att.Name))
			end
		end
	end

	-- 4. Transparencia
	if handle.Transparency > 0 then
		reprova(acc, ("Handle com Transparency %.2f: leitura automatica de conteudo escondido"):format(handle.Transparency))
	end

	-- 5. Lixo dentro do item
	for _, filho in handle:GetDescendants() do
		if filho:IsA("BaseScript") then
			reprova(acc, ("tem script dentro do Handle: %s"):format(filho.Name))
		elseif filho:IsA("Decal") or filho:IsA("Texture") then
			reprova(acc, ("tem %s dentro do Handle; a textura vai no MeshPart"):format(filho.ClassName))
		end
	end

	-- 6. Textura presente
	if handle:IsA("MeshPart") then
		local temSurface = handle:FindFirstChildWhichIsA("SurfaceAppearance") ~= nil
		if handle.TextureID == "" and not temSurface then
			atencao(acc, "MeshPart sem TextureID e sem SurfaceAppearance")
		end
	else
		atencao(acc, ("Handle e '%s', nao MeshPart"):format(handle.ClassName))
	end

	-- 7. Nome e descricao
	checkarNomeEDescricao(acc)
end

function checkarNomeEDescricao(acc: Accessory)
	checkarTextoInterno(acc)
end

function checkarTextoInterno(acc: Accessory)
	checkarTexto(acc)
end

function checkarTexto(acc: Accessory)
	checkarTexto_impl(acc)
end

function checkarTexto_impl(acc: Accessory)
	checkarTexto2(acc)
end

function checkarTexto2(acc: Accessory)
	local desc = acc:GetAttribute("Descricao")
	checkarTexto3(acc, desc)
end

function checkarTexto3(acc: Accessory, desc: any)
	checkarTexto(acc, "nome", acc.Name)
	if typeof(desc) == "string" then
		checkarTexto(acc, "descricao", desc)
	else
		atencao(acc, "sem atributo 'Descricao': a descricao nao foi checada")
	end
end

local pasta = ServerStorage:FindFirstChild("UGC_Check")
if not pasta then
	warn("[UGC] crie uma pasta chamada 'UGC_Check' em ServerStorage e ponha os Accessory dentro")
	return
end

local total = 0
for _, filho in pasta:GetChildren() do
	if filho:IsA("Accessory") then
		total += 1
		checkarAccessory(filho)
	else
		atencao(filho, ("nao e Accessory (e '%s'); ignorado"):format(filho.ClassName))
	end
end

print(("[UGC] %d itens checados | %d reprovas | %d atencoes"):format(total, reprovas, atencoes))
print("[UGC] o script nao conta triangulos nem le a imagem da textura. Isso e olho humano no Blender.")
Neste artigo