© DrHitch/Shutterstock.com
Terraingenerierung mit Unity

2 Terraingenerierung in Unity


Der nicht nur für Rezensenten wertvolle Wiederspielwert eines Spiels hängt direkt davon ab, wie viele Maps zur Verfügung stehen. Da das manuelle Erstellen von Inhalten schnell in Arbeit ausarten kann, wirkt die dynamische Generierung von – unendlich vielen – Terrains gleich doppelt attraktiv.

Wer sich in einer Bibliothek mit Informationen zur Terraingenerierung versorgen möchte, steht einer überwältigenden Datenmenge gegenüber. Dieses Kapitel stellt ohne Vollständigkeitsanspruch einige Verfahren vor, mit denen der Autor bislang erfolgreich war. Als Arbeitsumgebung dient dabei eine in Unity 4.6 realisierte Kombination aus Terrain, Wasserfläche, Main Camera und Directional Light. Andere Game Engines verhalten sich im Großen und Ganzen analog, die hier gezeigten Konzepte lassen sich ohne großen Aufwand auf andere Plattformen übertragen.

Die Kraft des Zufalls

Die im letzten Kapitel angesprochenen Terrains arbeiten mit einer Textur: Die Höhe des jeweiligen Objekts lässt sich durch Samplen des Farbwerts ermitteln. Es bietet sich somit an, das Terrain mit einem Skript auszustatten, das ein zufällig generiertes Gelände errechnet (Listing 2.1).

void Start() {
TerrainData myTD = ((Terrain)GetComponent ("Terrain")).terrainData;
float[,] newHM = new float[myTD.heightmapHeight, myTD.heightmapWidth];
//Y über X

for (int i=0; i<myTD.heightmapWidth; i++) {
for (int j=0; j<myTD.heightmapHeight; j++) {
newHM[j,i]=Random.Range(0f,0.5f);
}
}

myTD.SetHeights (0, 0, newHM);
}

Listing 2.1

Unity ruft Start() im Rahmen der Terraingenerierung auf. Die Methode schafft einen Verweis auf das TerrainData-Objekt, extrahiert die benötigten Informationen und nutzt sie zur Erzeugung eines neuen Heightmap-Arrays. Dieses wandert im nächsten Schritt per setHeight in das Terrain zurück: Als einziges Hindernis gilt die nach dem Schema Y über X aufgebaute Indizierung des Arrays.

Unity-Terrainobjekte kennen nur „positive“ Werte: Teilweise unter Wasser stehende Terrains lassen sich nur durch das Anheben der Wasserfläche realisieren. Damit sind wir hier fertig – Abbildung 2.1 zeigt das optisch nur wenig befriedigende Ergebnis.

image

Abbildung 2.1: Dieses Terrain sieht unschön aus

Glätte mich

Die „Abruptheit“ des Terrains lässt es nur wenig attraktiv erscheinen: Ein Hügel kann sich dank des Zufallsgenerators auch direkt neben einem Tal befinden. Ein Weg zur Lösung des Problems besteht darin, den Abstand zwischen den berechneten Punkten zu erhöhen und die Abstände dazwischen zu interpolieren.

An dieser Stelle wollen wir kurz innehalten und die Gelegenheit zur Reflektion nutzen. Unser Terrain ist nun in Form einer Funktion beschrieben, die den Höhenwert des jeweiligen Objekts aus seiner X- und seiner Y-Koordinate ermittelt. Mathematiker würden die Situation als Z=f(x,y) zusammenfassen.

Damit ist uns ein kleiner Exkurs erlaubt. Physiker beschreiben Schwingungen gern mit Sinus- oder Kosinusfunktionen. Wer die Funktion nach dem Schema Z= fa * (sin(x*f(x))+1) + fb * (cos(y*f(y))+1) aufstellt, hat eine grundlegende Welle – ihre Beispielimplementierung sieht wie in Listing 2.2 zu sehen aus und führt zum in Abbildung 2.2 gezeigten Resultat.

}
float Yf(int _y){
return 0.12f;
}
void Start () {
. . .
for (int i=0; i<myTD.heightmapWidth; i++) {
for (int j=0; j<myTD.heightmapHeight; j++) {
newHM[j,i]= 0.1f * (Mathf.Sin(i*Xf(i))+1f) + 0.2f * (MathfCos(j*Yf(j))+1f);
}
}

. . .

Listing 2.2

image

Abbildung 2.2: Sinus und Kosinus verhelfen zu natürlicherem Aussehen

Die Multiplikation des Funktionswerts mit einer Hilfsfunktion erlaubt das Glätten und Strecken des Sinus. Im Normalfall werden sie als Konstante ausgeführt – wer ihren Wert in Abhängigkeit des X- bzw. Y-Werts anpasst, kann die Schwingungsgeschwindigkeit der Funktion sektorenweise adjustieren. Achten Sie dabei allerdings darauf, nicht zu aggressiv vorz...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang