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 :
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() :
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() :
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() :
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 :
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}finkitxmlcodelatexdvpSoit, dans le code :
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.