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.
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.
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.
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 :
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.