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 - Bordures
III. Résumé▲
Cet épisode a pour but d'éliminer les bordures visibles entre les morceaux de terrain.
IV. Bogue▲
Au cours de l'épisode précédent, un bogue a été introduit. Celui-ci fait que certains morceaux de terrain ne disparaissent jamais.
Cela est provoqué par la non-mise à jour du tableau terrainChunksVisibileLastUpdate. En effet, la dernière fois, à travers la classe LODMesh, nous avons implémenté une méthode pour ajouter des modèles sans pour autant modifier le fonctionnement du tableau.
Pour corriger cela, le tableau devient statique et est mis à jour dans TerrainChunk::UpdateTerrainChunk() :
terrainChunksVisibleLastUpdate.
Add (
this
);
V. Éliminer les bordures▲
On remarque que si on modifie le décalage (« offset ») de la génération, le terrain change de forme. Aussi, la modification du décalage sur l'axe Y ne déplace pas le terrain dans la bonne direction.
Pour le second problème, il suffit de modifier l'opération dans le fichier Noise.cs :
float
offsetY =
prng.
Next (-
100000
,
100000
) -
offset.
y;
Ensuite, nous voulons que le décalage soit impacté par la fréquence et l'échelle (« scale ») :
float
sampleX =
(
x-
halfWidth +
octaveOffsets[
i].
x) /
scale *
frequency;
float
sampleY =
(
y-
halfHeight +
octaveOffsets[
i].
y) /
scale *
frequency;
Ce qui corrige la modification du terrain lors du changement du décalage.
Finalement, des bordures apparaissent, car lors de l'utilisation de Mathf.InverseLerp dans le fichier Noise.cs, la valeur maximale passée change pour chaque section de terrain.
La méthode utilisée jusque-là fonctionne très bien pour une génération de terrain finie.
Pour corriger cela, nous allons implémenter un autre mode de calcul pour la normalisation (sans pour autant enlever l'ancienne technique).
for
(
int
y =
0
;
y <
mapHeight;
y++
) {
for
(
int
x =
0
;
x <
mapWidth;
x++
) {
if
(
normalizeMode ==
NormalizeMode.
Local) {
noiseMap [
x,
y]
=
Mathf.
InverseLerp (
minLocalNoiseHeight,
maxLocalNoiseHeight,
noiseMap [
x,
y]
);
}
else
{
float
normalizedHeight =
(
noiseMap [
x,
y]
+
1
) /
(
maxPossibleHeight/
0
.
9f
);
noiseMap [
x,
y]
=
Mathf.
Clamp
(
normalizedHeight,
0
,
int
.
MaxValue);
}
}
}
La valeur maxPossibleHeight est calculée dans la première boucle de la même fonction :
float
amplitude =
1
;
float
frequency =
1
;
for
(
int
i =
0
;
i <
octaves;
i++
) {
float
offsetX =
prng.
Next (-
100000
,
100000
) +
offset.
x;
float
offsetY =
prng.
Next (-
100000
,
100000
) -
offset.
y;
octaveOffsets [
i]
=
new
Vector2 (
offsetX,
offsetY);
maxPossibleHeight +=
amplitude;
amplitude *=
persistance;
}
Par ces modifications, il est possible d'avoir des hauteurs dépassant 1. Par conséquent, le code de coloration est modifié pour s'assurer que l'intégralité du terrain aura une couleur appropriée :
Color[]
colourMap =
new
Color[
mapChunkSize *
mapChunkSize];
for
(
int
y =
0
;
y <
mapChunkSize;
y++
) {
for
(
int
x =
0
;
x <
mapChunkSize;
x++
) {
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
;
}
}
}
}
Il reste deux problèmes après ces modifications :
- les normales ne sont pas correctes sur les bordures ;
- la jointure entre deux niveaux de détail n'est pas parfaite.
Le second point est négligeable, car le défaut n'apparaît que si le joueur est loin et ne sera donc pas visible.
VI. Dimensionnement▲
Afin de rendre le terrain à des dimensions adéquates par rapport au joueur, nous ajoutons un facteur de redimensionnement (« scale ») prenant effet dans la classe TerrainChunk :
meshObject.
transform.
position =
positionV3 *
scale;
meshObject.
transform.
parent =
parent;
meshObject.
transform.
localScale =
Vector3.
one *
scale;
VII. Commenter▲
Vous pouvez commenter et donner vos avis dans la discussion associée sur le forum.