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

Carte de diminution du terrain

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 - Carte de diminution du terrain


III. Résumé

La carte de diminution du terrain permet de s'assurer que le terrain est complètement entouré d'eau. Ainsi, lors de la génération, nous appliquons un décalage des hauteurs générées par le bruit suivant la carte de diminution.
Cette nouvelle carte sera aussi générée à la volée.

IV. Implémentation

Créez un nouveau script C#, nommé FallOffGenerator.cs :

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

public static class FalloffGenerator {

    public static float[,] GenerateFalloffMap(int size) {
        float[,] map = new float[size,size];

        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                float x = i / (float)size * 2 - 1;
                float y = j / (float)size * 2 - 1;

                float value = Mathf.Max (Mathf.Abs (x), Mathf.Abs (y));
                map [i, j] = value;
            }
        }

        return map;
    }

La fonction GenerateFalloffMap() génère la carte (carrée) de diminution à la taille voulue.

V. Affichage du résultat

Il est toujours pratique d'afficher ce que nous venons de générer, ne serait-ce que pour confirmer que le résultat est celui attendu.

Pour cela, nous réutilisons le mécanisme mis en place précédemment, en ajoutant une entrée FalloffMap dans l'énumération et qui est utilisée dans la fonction DrawMapInEditor() :

MapGenerator.cs
Sélectionnez
public void DrawMapInEditor() {
    MapData mapData = GenerateMapData (Vector2.zero);

    MapDisplay display = FindObjectOfType<MapDisplay> ();
    if (drawMode == DrawMode.NoiseMap) {
        display.DrawTexture (TextureGenerator.TextureFromHeightMap (mapData.heightMap));
    } else if (drawMode == DrawMode.ColourMap) {
        display.DrawTexture (TextureGenerator.TextureFromColourMap (mapData.colourMap, mapChunkSize, mapChunkSize));
    } else if (drawMode == DrawMode.Mesh) {
        display.DrawMesh (MeshGenerator.GenerateTerrainMesh (mapData.heightMap, meshHeightMultiplier, meshHeightCurve, editorPreviewLOD), TextureGenerator.TextureFromColourMap (mapData.colourMap, mapChunkSize, mapChunkSize));
    } else if (drawMode == DrawMode.FalloffMap) {
        display.DrawTexture(TextureGenerator.TextureFromHeightMap(FalloffGenerator.GenerateFalloffMap(mapChunkSize)));
    }
}

On réutilise simplement la fonction DrawTexture() pour l'affichage.

VI. Utilisation de la carte

La carte de diminution n'est générée qu'une seule fois. Pour cela, la génération est lancée dans la méthode Awake() :

MapGenerator.cs
Sélectionnez
float[,] falloffMap;

void Awake() {
    falloffMap = FalloffGenerator.GenerateFalloffMap (mapChunkSize);
}

Toutefois, la carte ne sera générée que si on démarre le jeu. Il est donc aussi nécessaire d'ajouter la génération dans la méthode OnValidate() :

MapGenerator.cs
Sélectionnez
void OnValidate() {
    if (lacunarity < 1) {
        lacunarity = 1;
    }
    if (octaves < 0) {
        octaves = 0;
    }

    falloffMap = FalloffGenerator.GenerateFalloffMap (mapChunkSize);
}

Ensuite, dans la méthode GenerateMapData(), nous utilisons la nouvelle carte pour impacter les hauteurs :

MapGenerator.cs
Sélectionnez
MapData GenerateMapData(Vector2 centre) {
    float[,] noiseMap = Noise.GenerateNoiseMap (mapChunkSize, mapChunkSize, seed, noiseScale, octaves, persistance, lacunarity, centre + offset, normalizeMode);

    Color[] colourMap = new Color[mapChunkSize * mapChunkSize];
    for (int y = 0; y < mapChunkSize; y++) {
        for (int x = 0; x < mapChunkSize; x++) {
            if (useFalloff) {
                noiseMap [x, y] = Mathf.Clamp01(noiseMap [x, y] - falloffMap [x, y]);
            }
            float currentHeight = noiseMap [x, y];
            for (int i = 0; i < regions.Length; i++) {
                if (currentHeight >= regions [i].height) {
                    colourMap [y * mapChunkSize + x] = regions [i].colour;
                } else {
                    break;
                }
            }
        }
    }


    return new MapData (noiseMap, colourMap);
}

VII. Amélioration de la carte

La première version de la carte réduit trop les valeurs. Pour corriger cela, la carte sera générée suivant l'équation :

kitxmlcodelatexdvp\frac {x^a} {x^a + (1 - x)^a}finkitxmlcodelatexdvp

Soit, dans le code :

FalloffGenerator.cs
Sélectionnez
static float Evaluate(float value) {
    float a = 3;
    float b = 2.2f;

    return Mathf.Pow (value, a) / (Mathf.Pow (value, a) + Mathf.Pow (b - b * value, a));
}

VIII. 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 ni 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.