Como fazer reflexo parecido com o do Blender no Roblox Studio
Você sobe o Reflectance para 1 esperando ver a parede refletida na esfera e só aparece nuvem, porque o Roblox reflete o skybox e mais nada. Dá para chegar perto do Blender empilhando três camadas: Reflectance, SurfaceAppearance com os mapas exportados do Blender e um cenário espelhado embaixo do piso.
Rascunho assistido por IA, revisado, testado e editado por um humano antes de publicar. Ver Política Editorial. · Revisado por Gustavo Cantino, 15/09/2026 Política Editorial

Reflexo igual ao do Blender não existe no Roblox, e não é opção escondida em menu nenhum: é diferença de motor. No Blender, o Cycles traça o caminho da luz raio por raio e o EEVEE usa screen space reflection — os dois calculam de verdade o que está em volta do objeto. O renderizador do Roblox precisa rodar em celular Android de entrada, então ele não faz nem uma coisa nem outra: o que ele chama de reflexo é, na maior parte dos casos, uma consulta ao skybox (a caixa de céu que envolve o mapa inteiro).
O Roblox não tem ray tracing — e o que ele tem no lugar
A consequência prática é onde você perde a tarde. Você clica numa esfera, acha a propriedade Reflectance, arrasta de 0 para 1 esperando ver o chão e a parede aparecerem nela — e vê nuvem. Fecha a esfera dentro de uma sala sem janela: continua nuvem. Ela não sabe que existe parede ao lado, só sabe que existe céu. Aí começa a tentativa de compensar: troca o material para Neon, troca para Glass, sobe Reflectance de tudo para 1, e o mapa inteiro fica com aquela cara de plástico cromado.
Antes de qualquer coisa, dois painéis. O Explorer é o painel da direita que lista todos os objetos do jogo em árvore; o Properties fica logo abaixo dele e mostra as propriedades do objeto que você selecionou. Se algum dos dois não estiver aparecendo, abra a aba View na faixa de cima do Studio e clique em Explorer e em Properties. Todo o resto deste texto depende desses dois painéis abertos.
Outra coisa que economiza meia hora: a qualidade do sistema de iluminação fica em Lighting, um objeto que já vem dentro do jogo e aparece no Explorer. Selecione ele e, no Properties, procure a propriedade Technology. Ela tem um menu com Voxel, ShadowMap e Future. Reflexo decente só acontece em Future. E ela só muda por esse menu — script não muda:
-- Não funciona. Technology é alterado só pelo painel Properties, no Studio.
game:GetService("Lighting").Technology = Enum.Technology.FutureCom o Lighting ainda selecionado, procure também EnvironmentSpecularScale e EnvironmentDiffuseScale. São dois números de 0 a 1. Se o Specular estiver em 0, o céu não ilumina nem reflete em nada, e você pode mexer em Reflectance o dia inteiro sem ver diferença. Coloque os dois em 1 para testar.
As três camadas de reflexo, da mais barata para a mais cara
Camada 1 — Reflectance (leva 2 minutos e custa nada de performance). Clique numa Part no Explorer, vá no Properties e ache Reflectance. É um número de 0 a 1: 0 é fosco, 1 é espelho de céu. Para metal escovado, 0,15 a 0,3 já dá o brilho certo. Acima de 0,5 o objeto vira bola de discoteca. Essa camada só reflete o skybox, então ela depende de existir um Sky dentro do Lighting. Confira no Explorer: se não houver um objeto chamado Sky ali, passe o mouse sobre Lighting, clique no sinal de mais que aparece do lado e insira um Sky. Um skybox com nuvem, montanha e horizonte dá um reflexo muito mais convincente do que o céu azul liso padrão — e é literalmente a imagem que vai aparecer no seu "metal".
Regra que vale ouro para ambiente interno: quanto mais fechado o cenário, mais baixo o Reflectance. Uma sala sem janela com Reflectance 0,4 fica errada porque o Roblox vai refletir céu atravessando o teto. Em ambiente interno, fique entre 0,05 e 0,12.
Camada 2 — SurfaceAppearance, que é onde o seu material do Blender entra. Essa é a ponte real entre os dois programas. No Blender, o seu material provavelmente é um Principled BSDF com entradas Base Color, Metallic, Roughness e Normal. O Roblox tem um objeto que aceita exatamente esses quatro mapas: o SurfaceAppearance, que só funciona dentro de um MeshPart (a Part que veio de um modelo importado, não a caixa comum).
O caminho é este. No Blender, exporte ou baixe as quatro texturas em PNG. O Roblox aceita imagem de até 1024x1024 — mande maior e ela é reduzida, então já exporte nesse tamanho para você ver o resultado final e não uma surpresa. No Studio, abra View > Asset Manager, clique em Images, depois em Add Images, e selecione os arquivos. Eles entram na fila de moderação e só aparecem depois de aprovados; enquanto isso a textura fica em branco, e isso não é bug.
Com o MeshPart selecionado no Explorer, insira um SurfaceAppearance dentro dele (sinal de mais ao lado do nome do MeshPart). No Properties do SurfaceAppearance você vai ver ColorMap, MetalnessMap, RoughnessMap e NormalMap. Cole o ID de cada imagem no campo correspondente: Base Color vira ColorMap, Metallic vira MetalnessMap, Roughness vira RoughnessMap, Normal vira NormalMap. Campo deixado vazio é tratado como valor neutro (não metálico, bem rugoso). O RoughnessMap é uma imagem em tons de cinza onde preto é espelho e branco é fosco — e é ele que faz o chão de metal molhado parecer molhado. O MetalnessMap é o contrário do que parece: branco é metal, preto não é metal. Meio-termo cinza nos dois costuma ficar mais crível do que extremo.
Camada 3 — duplicar geometria, que é como se faz espelho e chão reflexivo de verdade. Nenhuma das duas camadas anteriores reflete objeto nenhum do seu mapa. Se você quer ver o personagem refletido no piso, ou uma poça refletindo o prédio, o jeito que funciona desde sempre é fazer uma cópia do cenário de cabeça para baixo, embaixo do piso, e deixar o piso translúcido por cima. O olho aceita na hora. Manualmente dá para fazer duplicando o modelo, girando 180 graus e descendo — mas errar o eixo em meio stud já estraga o efeito, e é por isso que existe o script abaixo.
O script que monta o reflexo de chão
O artefato faz a camada 3 inteira em um clique. Ele procura um Model no Workspace com o nome que você escolher, clona, espelha cada Part em torno de uma altura Y que você informa, tira tudo que não é visual (script, som, luz, ProximityPrompt), deixa as peças translúcidas e desliga colisão, sombra e raycast na cópia.
Para usar: no Explorer, selecione as peças do cenário que você quer ver refletidas, clique com o botão direito e escolha Group para virarem um Model; renomeie esse Model para Cenario. Depois, passe o mouse sobre ServerScriptService no Explorer (é uma pasta que já existe na árvore), clique no sinal de mais e insira um Script. Apague o conteúdo dele e cole o artefato.
Falta um número só: ALTURA_DO_PISO. É o Y da face de cima do piso, não o centro da Part. Selecione o piso, olhe Position e Size no Properties: se a Position em Y é 0,5 e o Size em Y é 1, a face de cima está em 1. Coloque 1 ali.
Aperte Play (F5). O script cria um Model chamado ReflexoFalso no Workspace. Ajuste TRANSPARENCIA_MINIMA — 0,55 é um começo razoável; mais perto de 0,7 fica reflexo discreto de piso polido. Falta o piso por cima: uma Part fina cobrindo tudo, Transparency por volta de 0,5, Reflectance 0,1 e cor escura. Sem essa Part por cima, o efeito parece um mapa duplicado bugado, não um reflexo.
Para deixar o reflexo salvo no lugar de gerar toda vez: com o jogo rodando, clique em ReflexoFalso no Explorer, Ctrl+C, aperte Stop e Ctrl+V. A área de transferência sobrevive ao Stop e a cópia fica permanente no seu mapa.
O erro que dobra o mapa e mata o FPS no celular
O erro caro é apontar o script para o mapa inteiro. Um cenário de 2.000 parts espelhado vira 4.000 parts para a GPU desenhar, e como a cópia é translúcida, cada uma delas custa mais caro do que uma peça opaca — transparência obriga o renderizador a desenhar em ordem, uma por uma. Em PC você talvez nem perceba; no celular o jogo engasga e o jogador sai. Por isso o artefato tem LIMITE_DE_PARTS em 400 e simplesmente se recusa a rodar acima disso, imprimindo o aviso no Output (abra em View > Output).
A saída não é aumentar o limite: é espelhar menos. Coloque dentro do Model Cenario só o que fica realmente visível no reflexo — as paredes e objetos próximos daquele piso, não o mapa inteiro nem o telhado. Reflexo de chão só mostra os primeiros metros ao redor mesmo.
O segundo erro, mais chato de descobrir: esquecer de desligar CanCollide e CanQuery na cópia. Se você duplicar na mão com Ctrl+D em vez de usar o script, a cópia espelhada continua sólida, e o jogador cai no chão e bate numa parede invisível embaixo do piso; pior, raycast de arma e de ferramenta acerta o reflexo e o tiro morre no nada. O script já força CanCollide = false, CanQuery = false, CanTouch = false e CastShadow = false em toda peça clonada.
Terceiro: modelo com texto ou detalhe assimétrico. O espelhamento inverte posição e rotação, mas não inverte a malha em si — uma placa escrita "LOJA" vai aparecer no reflexo virada, e um mesh com detalhe só de um lado vai aparecer no lado trocado. Para placa e letreiro, tire do Model Cenario e aceite que aquele pedaço não reflete.
O que medir depois
Meça a contagem de peças antes e depois. Abra View > Command Bar (a barrinha de digitar comando, geralmente na parte de baixo) e rode:
print(#workspace:GetDescendants())Anote o número antes de gerar o reflexo e depois. Se a diferença passou de umas poucas centenas, você espelhou cenário demais e é hora de tirar coisa do Model Cenario.
Depois, teste onde dói: na aba Test existe o emulador de dispositivo (Device). Escolha um celular, aperte Play e ande pelo piso reflexivo. Se a câmera arrastar quando você olha para baixo, o culpado é a transparência somada — suba TRANSPARENCIA_MINIMA para 0,7 ou corte metade das peças espelhadas.
Por último, compare com a referência do Blender lado a lado, uma imagem em cada tela. Quase sempre o que falta não é reflexo: é o RoughnessMap. Objeto com rugosidade uniforme parece brinquedo de plástico em qualquer motor, inclusive no Blender. Variar a rugosidade na textura resolve mais do que subir Reflectance.
Artefato pronto pra usar
--!strict
-- Reflexo falso de chao: duplica um Model, espelha embaixo do piso e deixa translucido.
-- Onde mora: Script (RunContext Legacy) dentro de ServerScriptService.
local Workspace = game:GetService("Workspace")
-- ========= CONFIGURACAO =========
local NOME_DO_MODELO: string = "Cenario" -- nome exato do Model no Workspace
local ALTURA_DO_PISO: number = 0 -- Y da FACE DE CIMA do piso
local TRANSPARENCIA_MINIMA: number = 0.55 -- 0 = opaco, 1 = invisivel
local LIMITE_DE_PARTS: number = 400 -- acima disso o script avisa e nao duplica
-- ================================
-- Espelha um CFrame em torno de um plano horizontal (Y = planoY).
-- Inverte a posicao em Y e reflete a rotacao (M * R * M), que continua sendo
-- uma rotacao valida: o Roblox nao aceita escala negativa dentro de um CFrame.
local function espelharCFrame(cf: CFrame, planoY: number): CFrame
local x, y, z, r00, r01, r02, r10, r11, r12, r20, r21, r22 = cf:GetComponents()
return CFrame.new(
x, (2 * planoY) - y, z,
r00, -r01, r02,
-r10, r11, -r12,
r20, -r21, r22
)
end
-- Tira da copia tudo que nao e visual: script, som, luz, prompt, humanoide.
local function limparCopia(raiz: Instance): ()
for _, obj in ipairs(raiz:GetDescendants()) do
if obj:IsA("LuaSourceContainer")
or obj:IsA("Sound")
or obj:IsA("ParticleEmitter")
or obj:IsA("Light")
or obj:IsA("Humanoid")
or obj:IsA("ClickDetector")
or obj:IsA("ProximityPrompt") then
obj:Destroy()
end
end
end
local function contarParts(raiz: Instance): number
local total = 0
for _, obj in ipairs(raiz:GetDescendants()) do
if obj:IsA("BasePart") then
total += 1
end
end
return total
end
local original = Workspace:FindFirstChild(NOME_DO_MODELO)
if not original or not original:IsA("Model") then
warn(("[Reflexo] Nao achei um Model chamado '%s' dentro do Workspace."):format(NOME_DO_MODELO))
return
end
local quantidade = contarParts(original)
if quantidade > LIMITE_DE_PARTS then
warn(("[Reflexo] '%s' tem %d parts; o mapa iria para %d. Reduza o Model ou suba LIMITE_DE_PARTS.")
:format(NOME_DO_MODELO, quantidade, quantidade * 2))
return
end
local antigo = Workspace:FindFirstChild("ReflexoFalso")
if antigo then
antigo:Destroy()
end
local reflexo = original:Clone()
reflexo.Name = "ReflexoFalso"
limparCopia(reflexo)
for _, obj in ipairs(reflexo:GetDescendants()) do
if obj:IsA("BasePart") then
obj.Anchored = true -- nao cai nem e empurrado
obj.CanCollide = false -- jogador nao bate na copia
obj.CanQuery = false -- raycast de ferramenta ignora
obj.CanTouch = false
obj.CastShadow = false -- sombra embaixo do piso so custa GPU
obj.Transparency = math.max(obj.Transparency, TRANSPARENCIA_MINIMA)
obj.CFrame = espelharCFrame(obj.CFrame, ALTURA_DO_PISO)
end
end
reflexo.Parent = Workspace
print(("[Reflexo] 'ReflexoFalso' criado com %d parts espelhadas em Y = %.2f.")
:format(quantidade, ALTURA_DO_PISO))


