A geração procedural sustenta os principais roguelikes e RPGs no Roblox. Sem arquitetura algorítmica correta, o servidor sofre sobrecarga de memória e travamentos.
Ao integrar o particionamento BSP para salas, Delaunay para caminhos orgânicos e o recurso nativo `StreamingEnabled`, é possível criar masmorras gigantescas e leves.
1. Divisão de Salas com Particionamento Espacial Binário (BSP)
Subdivisão recursiva para distribuição proporcional de salas:
- Corte Recursivo: O espaço total é dividido repetidamente na vertical ou horizontal até que os nós alcancem as dimensões pretendidas.
- Controle de Proporção: Mantém proporções entre 1:1 e 1:2.5, impedindo a criação de quartos excessivamente estreitos.
- Inscrição sem Colisão: As salas são geradas dentro de cada nó folha, eliminando sobreposições sem exigir checagens pesadas de física.
2. Corredores Orgânicos: Triangulação Delaunay & Árvore Geradora Mínima (MST)
Conectando salas de forma contínua sem becos sem saída:
- Nuvem de Centroides: Conecta o centro de todas as salas por meio de uma malha 2D de Delaunay.
- Algoritmo MST: Elimina arestas redundantes garantindo que cada sala esteja acessível pelo menor trajeto total.
- Reinjeção de Ciclos (15%): Adiciona algumas ligações de volta para permitir trajetos alternativos e exploração rica.
3. Roteamento em Grade e Instanciação Modular de Peças
Transformando grafos teóricos em blocos tridimensionais no Roblox:
- Conexões em Ângulo Reto: Corredores ortogonais conectam os pontos de acesso das portas de cada ambiente.
- Autotiling 4-Bits: Seleção automática de paredes retas, cantos e cruzamentos conforme as peças vizinhas.
- Otimização de Geometria: Soldagem e fusão de malhas para reduzir a contagem de peças em até 90%.
-- Módulo de Particionamento Espacial Binário (BSP)
local BSPNode = {}
BSPNode.__index = BSPNode
function BSPNode.new(x, z, width, depth)
local self = setmetatable({}, BSPNode)
self.X, self.Z = x, z
self.Width, self.Depth = width, depth
self.LeftChild = nil
self.RightChild = nil
self.Room = nil
return self
end
function BSPNode:Split(minSize)
if self.LeftChild or self.RightChild then return false end
local splitHorizontal = math.random() > 0.5
if self.Width > self.Depth and (self.Width / self.Depth) >= 1.25 then
splitHorizontal = false
elseif self.Depth > self.Width and (self.Depth / self.Width) >= 1.25 then
splitHorizontal = true
end
local maxDimension = (splitHorizontal and self.Depth or self.Width) - minSize
if maxDimension <= minSize then return false end
local splitPos = math.random(minSize, maxDimension)
if splitHorizontal then
self.LeftChild = BSPNode.new(self.X, self.Z, self.Width, splitPos)
self.RightChild = BSPNode.new(self.X, self.Z + splitPos, self.Width, self.Depth - splitPos)
else
self.LeftChild = BSPNode.new(self.X, self.Z, splitPos, self.Depth)
self.RightChild = BSPNode.new(self.X + splitPos, self.Z, self.Width - splitPos, self.Depth)
end
return true
end
return BSPNode
4. Gestão de Memória e Arquitetura com StreamingEnabled
Masmorras com mais de 100 salas operando perfeitamente em celulares com 2GB de RAM:
- ModelStreamingMode.Atomic: Carrega cômodos inteiros de uma só vez para evitar buracos no chão.
- Particionamento em Chunks de 64x64 studs: Desativa cálculos de física em setores distantes do jogador.
- Culling de Oclusão: Portas fechadas evitam a renderização desnecessária de câmaras fora do campo visual.
5. Sincronização por Semente (Seed) e Controle no Servidor
Garantindo segurança total e zero lag de replicação de mapa:
- Replicação de Semente: O envio de um único número inteiro permite ao cliente reconstruir o mapa exato localmente.
- Entidades no Servidor: Monstros, armadilhas e baús são calculados e controlados exclusivamente pelo servidor.
- NavMesh Automatizado: Configuração de PathfindingModifier no piso para navegação inteligente dos inimigos.
Frequently Asked Questions
Por que usar BSP em vez de posicionar salas aleatoriamente?
O posicionamento aleatório exige checagens de colisão complexas e deixa espaços vazios. O BSP divide o espaço de maneira equilibrada e sem sobreposições.
Qual o papel da triangulação Delaunay com MST?
Conectar salas próximas com naturalidade e assegurar que nenhum cômodo fique isolado ou com caminhos excessivamente repetitivos.
Como o StreamingEnabled ajuda em mapas extensos?
Ele carrega na memória apenas os trechos próximos ao usuário, economizando memória em aparelhos móveis.
Como evitar discrepâncias de mapa entre cliente e servidor?
Basta compartilhar a mesma semente matemática, permitindo que ambos os lados construam o mesmo terreno sem transmissão de dados pesados.