Auteur : Sagaert Auguste

Chapitre 2 TD 3 – Implémentation d’un générateur de grottes

Résumé

Ce rapport présente la réalisation d’un générateur de grottes procédural sous Unity reposant sur un automate cellulaire 2D et deux moteurs de rendu de maillage : un rendu “cubes fusionnés” (WallGenerator) et un rendu par Marching Squares. Nous détaillons l’architecture des scripts, les règles de l’AC, les choix d’implémentation, la suite pour l’intégration dans le projet.

1. Contexte et objectifs pédagogiques

L’objectif est de maîtriser la génération procédurale sur grille binaire (mur/vide) et de sculpter une géométrie de grotte à partir d’un bruit initial. Le flux est découpé en deux parties :

  • La logique de carte : assurée par CaveGenerator
  • La production du maillage : confiée à des générateurs interchangeables dérivés de MeshGenerator

Cette séparation permet de comparer, à paramètres identiques, un rendu par instanciation puis fusion de cubes et un rendu par Marching Squares.

2. Génération de la carte

2.1 Initialisation aléatoire

L’initialisation crée un bruit binaire avec une bordure systématiquement marquée comme mur, ce qui ferme la carte. La graine peut être fixée pour garantir la reproductibilité ou tirée aléatoirement si useRandomSeed est activé.

Initialisation

2.2 Fonctions utilitaires

  • isWall(c, r) : traite toute coordonnée hors carte comme un mur
  • GetSurroundingWallCount(c, r, size) : compte les cellules murales dans un voisinage de rayon 1 ou 2

2.3 Règles de l’automate

Mode de base (clean = false) :

  • Une cellule murale reste mur si le nombre de voisins murs est supérieur à 3
  • Une cellule vide devient mur si elle possède au moins 5 voisins murs ou si le comptage sur rayon 2 est inférieur ou égal à 2

Mode Clean (clean = true) :

  • Une cellule vide devient mur dès que le nombre de voisins murs atteint 5, ce qui supprime les grandes cavités et lisse la carte

Exemple 1

Exemple 2

2.4. Contrôles & Cycle de vie

  • Espace : applique une itération AC (règles par défaut)
  • G : bascule vers l’autre jeu de règles et applique
  • N : régénère un nouveau bruit de départ

3. Rendu des grottes

3.1. Rendu par cubes

Principe : instancier wallCube (1×1×1) sur chaque cellule mur puis fusionner en un unique maillage.

Étapes :

  1. Destruction des anciens enfants
  2. Boucle carte → Instantiate(wallCube, pos) si map[c,r] == 1
  3. Décalage de transform.position pour centrer la carte
  4. MergeCubes() : GetComponentsInChildren<MeshFilter>()CombineMeshes
  5. mesh.indexFormat = IndexFormat.UInt32 si beaucoup de sommets

Avantages : simple, visuel, parfait pour comprendre le pipeline carte→mesh.

Rendu cubes

3.2 Rendu lissé par Marching Squares

Cette approche reconstruit un contour continu aux interfaces mur/vide, ce qui produit un maillage plus léger, des bords lissés et une meilleure tenue aux grandes tailles de carte en réduisant les sommets redondants.

4. Extension - SewerGenerator

L’extension vise la génération d’un réseau d’égouts procédural sur une grille dédiée, synchronisé avec la carte de surface. La grille 3D réemploie l’automate cellulaire avec pondération directionnelle pour favoriser des couloirs rectilignes et des carrefours de type T/+. Le maillage est reconstruit par un MarchingCubesGenerator afin de produire tunnels, parois et voûtes.

Égouts 1

Égouts 2

Prochaines étapes :

  1. Fusion des couches (ville + égouts) dans la scène principale
  2. Optimisation des intersections
  3. Accessoires narratifs : échelles, vannes, passerelles, grilles
  4. Gameplay : points d’entrée/sortie, balises NavMesh, volumes audio réverbération
  5. Performance : HLOD, lightmaps séparées, etc.

← Retour à Sagaert Auguste