I am relatively new to Terrain Generation in Unity, and am currently stuck in one place. I have followed Brackey's tutorial on terrain generation, and in that tutorial, he uses something like this:
float y = Mathf.PerlinNoise(x, z) * 2f;
To manipulate the height of the terrain. I also followed Sebastian Lague's tutorial on this. This is where I am stuck.
I want to use Sebastian Lague's Noise.cs
file that he created (can be found on his GitHub) to manipulate the terrain height.
The reason is because this noise generator, rather than Mathf.PerlinNoise()
, gives you a much better control over the texture it outputs. The problem is, Noise.cs
will return a 2D float array, while Mathf.PerlinNoise()
returns a 1D float value. Is there a way for Noise.cs
to return a float value, just like Mathf's function?
Noise.cs:
using UnityEngine;
using System.Collections;
public static class Noise {
public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset) {
float[,] noiseMap = new float[mapWidth,mapHeight];
System.Random prng = new System.Random (seed);
Vector2[] octaveOffsets = new Vector2[octaves];
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);
}
if (scale <= 0) {
scale = 0.0001f;
}
float maxNoiseHeight = float.MinValue;
float minNoiseHeight = float.MaxValue;
float halfWidth = mapWidth / 2f;
float halfHeight = mapHeight / 2f;
for (int y = 0; y < mapHeight; y++) {
for (int x = 0; x < mapWidth; x++) {
float amplitude = 1;
float frequency = 1;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++) {
float sampleX = (x-halfWidth) / scale * frequency + octaveOffsets[i].x;
float sampleY = (y-halfHeight) / scale * frequency + octaveOffsets[i].y;
float perlinValue = Mathf.PerlinNoise (sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistance;
frequency *= lacunarity;
}
if (noiseHeight > maxNoiseHeight) {
maxNoiseHeight = noiseHeight;
} else if (noiseHeight < minNoiseHeight) {
minNoiseHeight = noiseHeight;
}
noiseMap [x, y] = noiseHeight;
}
}
for (int y = 0; y < mapHeight; y++) {
for (int x = 0; x < mapWidth; x++) {
noiseMap [x, y] = Mathf.InverseLerp (minNoiseHeight, maxNoiseHeight, noiseMap [x, y]);
}
}
return noiseMap;
}
}
MeshGenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class MeshGenerator : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
public int xSize = 20;
public int zSize = 20;
int mapWidth;
int mapHeight;
int seed;
float scale;
int octaves;
float persistance;
float lacunarity;
Vector2 offset;
// Start is called before the first frame update
void Start()
{
// Initialize everything
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
void CreateShape()
{
// Creating the grid of vertices
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
// Setting vertex positions
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
//float y = Mathf.PerlinNoise(x * .3f, z * .3f) * 2f;
float y = Noise.GenerateNoiseMap(mapWidth, mapHeight, seed, scale, octaves, persistance, lacunarity, offset);
vertices[i] = new Vector3(x, y, z);
i++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
}
void UpdateMesh()
{
// Clear mesh data, reset with above vars and recalculate normals
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
private void OnDrawGizmos()
{
if (vertices == null) return;
Gizmos.color = Color.red;
// Draw Vertex Gizmos
for (int i = 0; i < vertices.Length; i++)
{
Gizmos.DrawSphere(vertices[i], .1f);
}
}
}
I've figured it out, I would've had to put
vertices[i] = new Vector3(x, y[x, z], z);
Now I've already tried this, but I suppose visual studio bugged and did not save it properly. Anyways, yes, I just needed to use x/y to pick out my float.