Unity - Génération procédurale de terrain

Implémentation basique du bruit et visualisation

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Cette série explique comment générer de manière procédurale des continents dans Unity.
Vous pouvez retrouver les autres épisodes de cette série dans le sommaire dédié.

II. Vidéo


Unity - Génération procédurale de terrain - Bruit


III. Résumé

Au cours de cette vidéo, vous allez apprendre à générer votre carte des hauteurs grâce au bruit de Perlin.

Unity fournit une fonction, PerlinNoise, pour obtenir le bruit de Perlin.

Le bruit de Perlin génère toujours la même valeur pour des coordonnées entières.

III-A. Implémentation

III-A-1. Script

Créez un nouveau script, appelé Noise.cs. Sachant que nous n'allons pas appliquer le bruit à un objet de la scène, nous pouvons enlever l'héritage de MonoBehavior. Aussi, le script ne sera pas instancié plusieurs fois, donc la classe peut être statique.

La classe implémente une méthode GenerateNoiseMap retournant un tableau 2D de valeurs flottantes.

Noise.cs
Sélectionnez
using UnityEngine;
using System.Collections;

public static class Noise {

    public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, float scale) {
        float[,] noiseMap = new float[mapWidth,mapHeight];

        if (scale <= 0) {
            scale = 0.0001f;
        }

        for (int y = 0; y < mapHeight; y++) {
            for (int x = 0; x < mapWidth; x++) {
                float sampleX = x / scale;
                float sampleY = y / scale;

                float perlinValue = Mathf.PerlinNoise (sampleX, sampleY);
                noiseMap [x, y] = perlinValue;
            }
        }

        return noiseMap;
    }

}

Le paramètre scale permet d'éviter de passer des valeurs entières à la fonction Mathf.PerlinNoise().

Ensuite, vous allez implémenter une méthode pour visualiser le résultat.

Créez un autre script, appelé MapGenerator.cs. Par la même occasion, créez un objet vide dans la scène. Placez-le au centre de la scène et associez-lui le script.

MapGenerator.cs
Sélectionnez
using UnityEngine;
using System.Collections;

public class MapGenerator : MonoBehaviour {

    public int mapWidth;
    public int mapHeight;
    public float noiseScale;

    public bool autoUpdate;

    public void GenerateMap() {
        float[,] noiseMap = Noise.GenerateNoiseMap (mapWidth, mapHeight, noiseScale);


        MapDisplay display = FindObjectOfType<MapDisplay> ();
        display.DrawNoiseMap (noiseMap);
    }
    
}

Le seul but du script est d'appeler le script de génération de bruit et d'envoyer les valeurs générées à la classe d'affichage.

L'affichage se fait grâce à un troisième script, MapDisplay.cs, lui aussi associé à l'objet vide créé précédemment. Le script permet de transformer la grille de valeurs provenant du bruit de Perlin en une texture.

 
Sélectionnez
using UnityEngine;
using System.Collections;

public class MapDisplay : MonoBehaviour {

    public Renderer textureRender;

    public void DrawNoiseMap(float[,] noiseMap) {
        int width = noiseMap.GetLength (0);
        int height = noiseMap.GetLength (1);

        Texture2D texture = new Texture2D (width, height);

        Color[] colourMap = new Color[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                colourMap [y * width + x] = Color.Lerp (Color.black, Color.white, noiseMap [x, y]);
            }
        }
        texture.SetPixels (colourMap);
        texture.Apply ();

        textureRender.sharedMaterial.mainTexture = texture;
        textureRender.transform.localScale = new Vector3 (width, 1, height);
    }
    
}

Il est plus rapide de générer un tableau des couleurs et de définir les couleurs de la texture grâce à ce dernier que de définir la couleur des pixels un par un.

La couleur est une couleur définie entre du noir et du blanc suivant la valeur du bruit grâce à la méthode Color.Lerp().

Afin que l'on puisse visualiser la texture dans l'éditeur, vous devez utiliser shaderMaterial (documentation) et non material (documentation) pour définir la texture du matériau.

La texture générée sera affichée sur un objet « Plane » placé au centre de la scène. Vous pouvez aussi lui retirer son « Collider », celui-ci étant inutile dans ce cas.

Finalement, il ne reste plus qu'à définir le plan dans lequel afficher la texture dans l'éditeur et créer un nouveau matériau ayant pour shader « Unlit Texture ». Pour pouvoir appeler le script de génération dans l'éditeur, il est nécessaire de créer un nouveau script, nommé MapGeneratorEditor.cs :

MapGeneratorEditor.cs
Sélectionnez
using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor (typeof (MapGenerator))]
public class MapGeneratorEditor : Editor {

    public override void OnInspectorGUI() {
        MapGenerator mapGen = (MapGenerator)target;

        if (DrawDefaultInspector ()) {
            if (mapGen.autoUpdate) {
                mapGen.GenerateMap ();
            }
        }

        if (GUILayout.Button ("Generate")) {
            mapGen.GenerateMap ();
        }
    }
}

Il est important que la texture générée ait une taille non nulle, sinon l'éditeur peut crasher.

IV. Commenter

Vous pouvez commenter et donner vos avis dans la discussion associée sur le forum.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2017 Unity Technologies. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.