La génération procédurale est le pilier des jeux roguelike et de survie sur Roblox. Sans optimisation algorithmique, les cartes surchargent rapidement la mémoire vive.
En combinant le découpage BSP, la triangulation de Delaunay et le système natif `StreamingEnabled`, vous pouvez générer des donjons immenses sans le moindre ralentissement.
1. Partitionnement Spatial Binaire (BSP) pour des Salles Équilibrées
Subdivision récursive évitant tout chevauchement:
- Découpe Récursive: L'espace global est scindé en sous-sections de ratios aléatoires jusqu'à obtenir la granularité désirée.
- Contraintes de Format: Maintien d'un ratio largeur/longueur équilibré pour éviter les pièces étriquées.
- Inscription Autonome: Chaque pièce s'inscrit dans sa partition, éliminant les calculs lourds de collision géométrique.
2. Réseau de Couloirs: Delaunay & Arbre Couvrant Minimal (MST)
Assurer une circulation fluide sans culs-de-sac:
- Nuage de Centroïdes: Les centres des salles forment un graphe de Delaunay reliant les pièces voisines.
- Arbre Couvrant Minimal (MST): Élimine les boucles superflues tout en garantissant l'accès à chaque pièce.
- Réinjection de Boucles (15%): L'ajout de liaisons complémentaires crée des itinéraires alternatifs indispensables au gameplay.
3. Traçage des Couloirs & Assemblage Modulaire
Conversion du graphe en blocs réels dans Roblox:
- Trajectoires Orthogonales: Jonctions en angle droit reliant les ouvertures murales de chaque pièce.
- Autotiling 4-Bits: Sélection automatique des sols, murs droits et carrefours selon la disposition des cases.
- Fusion d'Instances: Regroupement des parties soudées pour réduire de 90% l'empreinte physique du serveur.
-- Module de partitionnement spatial binaire (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. Optimisation Mémoire & StreamingEnabled
Exécuter de vastes donjons sur des smartphones à mémoire limitée:
- ModelStreamingMode.Atomic: Chargement unitaire des salles pour éviter les chutes dans le vide.
- Découpage en Chunks de 64x64 studs: Suspension de la physique sur les sections distantes.
- Culling d'Occlusion: Masquage des pièces fermées pour soulager la carte graphique du client.
5. Synchronisation par Graine & Autorité Serveur
Garantir l'intégrité du jeu et éliminer la triche:
- Graine Aléatoire (Seed): Un entier de 32 bits partagé permet une reconstruction locale identique sans lag réseau.
- Apparition d'Entités Sécurisée: Monstres, coffres et pièges sont gérés strictement par le serveur.
- Maillage NavMesh: Paramétrage des PathfindingModifiers pour un guidage parfait des créatures.
Frequently Asked Questions
Pourquoi privilégier le BSP au placement aléatoire simple?
Le placement aléatoire entraîne des collisions et des espaces vides. Le BSP répartit uniformément les salles sans risque de chevauchement.
À quoi sert la triangulation de Delaunay avec le MST?
Elle détermine les voisins logiques puis extrait le chemin le plus court reliant l'ensemble des pièces sans impasses.
En quoi StreamingEnabled est-il crucial?
Il charge et décharge dynamiquement les pièces selon la position du joueur, permettant de supporter des cartes gigantesques.
Comment synchroniser le donjon sans latence?
En partageant uniquement la graine de calcul entre le serveur et le client pour une construction locale symétrique.